summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2026-01-20 03:56:38 +0200
committerAndrey Lihatskiy <alihatskiy@productengine.com>2026-01-20 03:56:38 +0200
commit30e7621140a3cbf4c911f596c1325f4b7eae25a6 (patch)
treec91ced079bd5b84eb5cd3c7a9c3b3b7bb8367057
parent7d616292ad664472ffa79cc0cd447096a18e72ba (diff)
parent8bacd29bcb36b87ca237fe3ff9459461c1a4cf55 (diff)
Merge branch 'develop-linux' into project/lua_editor
# Conflicts: # indra/newview/llpreviewscript.cpp
-rw-r--r--.github/workflows/build.yaml20
-rw-r--r--.github/workflows/cla.yaml2
-rw-r--r--.github/workflows/pre-commit.yaml2
-rw-r--r--[-rwxr-xr-x].gitignore0
-rw-r--r--[-rwxr-xr-x]LICENSE0
-rw-r--r--[-rwxr-xr-x]doc/LGPL-license.txt0
-rw-r--r--[-rwxr-xr-x]doc/LICENSE-logos.txt0
-rw-r--r--[-rwxr-xr-x]doc/LICENSE-source.txt0
-rw-r--r--[-rwxr-xr-x]doc/contributions.txt0
-rw-r--r--[-rwxr-xr-x]doc/releasenotes-where.txt0
-rw-r--r--[-rwxr-xr-x]doc/translations.txt0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/__init__.py0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/ipc/__init__.py0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/ipc/compatibility.py0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/ipc/llmessage.py0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/ipc/tokenstream.py0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/util/__init__.py0
-rw-r--r--[-rwxr-xr-x]indra/lib/python/indra/util/llmanifest.py0
-rw-r--r--indra/llappearance/llpolymesh.cpp2
-rw-r--r--indra/llappearance/lltexlayer.cpp18
-rw-r--r--indra/llappearanceutility/llappappearanceutility.cpp2
-rw-r--r--[-rwxr-xr-x]indra/llappearanceutility/llprocessparams.cpp0
-rw-r--r--[-rwxr-xr-x]indra/llaudio/llaudiodecodemgr.cpp2
-rw-r--r--[-rwxr-xr-x]indra/llaudio/llaudioengine.h0
-rw-r--r--indra/llcharacter/CMakeLists.txt4
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp2
-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.txt2
-rw-r--r--indra/llcommon/fsyspath.h4
-rw-r--r--[-rwxr-xr-x]indra/llcommon/hexdump.h0
-rw-r--r--indra/llcommon/llapp.cpp4
-rw-r--r--indra/llcommon/llapr.cpp220
-rw-r--r--indra/llcommon/llapr.h17
-rw-r--r--indra/llcommon/llcrc.cpp2
-rw-r--r--indra/llcommon/llcrc.h2
-rw-r--r--indra/llcommon/llerror.cpp10
-rw-r--r--indra/llcommon/llfile.cpp1096
-rw-r--r--indra/llcommon/llfile.h811
-rwxr-xr-xindra/llcommon/llpointer.cpp43
-rw-r--r--indra/llcommon/llpointer.h291
-rw-r--r--indra/llcommon/llprocessor.cpp4
-rw-r--r--indra/llcommon/llprofilercategories.h9
-rw-r--r--indra/llcommon/llsys.cpp6
-rw-r--r--indra/llcommon/lluuid.cpp46
-rw-r--r--indra/llcommon/lluuid.h2
-rw-r--r--indra/llcommon/tests/llfile_test.cpp299
-rw-r--r--indra/llcommon/tests/llleap_test.cpp20
-rw-r--r--indra/llcommon/tests/llprocess_test.cpp52
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp12
-rw-r--r--indra/llcommon/workqueue.cpp22
-rw-r--r--indra/llcorehttp/httpcommon.cpp4
-rw-r--r--indra/llcorehttp/httpcommon.h6
-rw-r--r--[-rwxr-xr-x]indra/llcorehttp/llhttpconstants.cpp0
-rw-r--r--[-rwxr-xr-x]indra/llcorehttp/llhttpconstants.h0
-rw-r--r--[-rwxr-xr-x]indra/llcorehttp/tests/llcorehttp_test.cpp0
-rw-r--r--indra/llfilesystem/lldir.cpp63
-rw-r--r--indra/llfilesystem/lldir.h2
-rw-r--r--indra/llfilesystem/lldir_linux.cpp18
-rw-r--r--indra/llfilesystem/lldir_linux.h1
-rw-r--r--indra/llfilesystem/lldir_mac.cpp24
-rw-r--r--indra/llfilesystem/lldir_mac.h1
-rw-r--r--indra/llfilesystem/lldir_win32.cpp18
-rw-r--r--indra/llfilesystem/lldir_win32.h1
-rw-r--r--indra/llfilesystem/lldiriterator.cpp10
-rw-r--r--indra/llfilesystem/lldiskcache.cpp102
-rw-r--r--indra/llfilesystem/llfilesystem.cpp104
-rw-r--r--indra/llfilesystem/llfilesystem.h7
-rw-r--r--indra/llfilesystem/tests/lldir_test.cpp6
-rw-r--r--indra/llimage/llimage.cpp36
-rw-r--r--indra/llimage/llimage.h8
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp2
-rw-r--r--indra/llimage/llimagetga.cpp2
-rw-r--r--indra/llmath/llvolumemgr.cpp1
-rw-r--r--indra/llmath/v3math.h9
-rw-r--r--indra/llmessage/llassetstorage.cpp4
-rw-r--r--indra/llmessage/lltransfersourcefile.cpp2
-rw-r--r--indra/llmessage/lltransfertargetfile.cpp2
-rw-r--r--indra/llmessage/llxfer_file.cpp16
-rw-r--r--indra/llmessage/message.cpp4
-rw-r--r--indra/llmessage/tests/lldatapacker_test.cpp4
-rw-r--r--indra/llmessage/tests/llmessageconfig_test.cpp2
-rw-r--r--indra/llmessage/tests/message_test.cpp2
-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/llshadermgr.cpp24
-rw-r--r--indra/llui/lllineeditor.cpp1
-rw-r--r--indra/llui/lllineeditor.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/llui/lluicolortable.cpp2
-rw-r--r--indra/llui/llxuiparser.cpp6
-rw-r--r--[-rwxr-xr-x]indra/llui/tests/llurlentry_stub.cpp0
-rw-r--r--indra/llwebrtc/llwebrtc.cpp3
-rw-r--r--indra/llxml/llcontrol.cpp31
-rw-r--r--indra/llxml/llcontrol.h2
-rw-r--r--indra/llxml/llxmlparser.cpp4
-rw-r--r--indra/llxml/tests/llcontrol_test.cpp2
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/base/media_plugin_base.exp0
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp0
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp0
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc0
-rw-r--r--[-rwxr-xr-x]indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc0
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--[-rwxr-xr-x]indra/newview/app_settings/llsd.xsd0
-rw-r--r--[-rwxr-xr-x]indra/newview/app_settings/message.xml0
-rw-r--r--indra/newview/app_settings/settings.xml26
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl137
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl126
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyF.glsl118
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyV.glsl123
-rw-r--r--indra/newview/featuretable.txt18
-rw-r--r--indra/newview/featuretable_linux.txt18
-rw-r--r--indra/newview/featuretable_mac.txt17
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/darwin/dmg-cleanup.applescript0
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/darwin/release-dmg/Applications-alias.r0
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/darwin/release-dmg/_DS_Storebin12292 -> 12292 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_de.nsi0
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_es.nsibin13790 -> 13790 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_fr.nsibin14302 -> 14302 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_it.nsibin13528 -> 13528 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_ja.nsibin10698 -> 10698 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_pt-br.nsibin13970 -> 13970 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_ru.nsibin13264 -> 13264 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_tr.nsibin13174 -> 13174 bytes
-rw-r--r--[-rwxr-xr-x]indra/newview/installers/windows/lang_zh.nsibin10154 -> 10154 bytes
-rw-r--r--indra/newview/llagentcamera.cpp8
-rw-r--r--indra/newview/llappdelegate-objc.mm8
-rw-r--r--indra/newview/llappviewer.cpp47
-rw-r--r--indra/newview/llavataractions.cpp2
-rw-r--r--indra/newview/llconversationlog.cpp4
-rw-r--r--indra/newview/lldrawable.cpp8
-rw-r--r--indra/newview/lldrawpoolalpha.cpp2
-rw-r--r--indra/newview/lldrawpoolbump.cpp2
-rw-r--r--indra/newview/llface.cpp6
-rw-r--r--indra/newview/llfloatereditenvironmentbase.cpp2
-rw-r--r--[-rwxr-xr-x]indra/newview/llfloatermap.cpp0
-rw-r--r--indra/newview/llfloatermarketplace.cpp35
-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.cpp33
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llfloaterpreferencesgraphicsadvanced.cpp13
-rw-r--r--indra/newview/llfloaterregioninfo.cpp15
-rw-r--r--indra/newview/llfloateruipreview.cpp39
-rw-r--r--[-rwxr-xr-x]indra/newview/llfloaterworldmap.cpp0
-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.cpp15
-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/llkeyconflict.cpp2
-rw-r--r--indra/newview/lllocalbitmaps.cpp20
-rw-r--r--indra/newview/lllocalbitmaps.h3
-rw-r--r--indra/newview/lllocalgltfmaterials.cpp18
-rw-r--r--indra/newview/lllocalgltfmaterials.h3
-rw-r--r--indra/newview/lllogchat.cpp12
-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/llmutelist.cpp8
-rw-r--r--[-rwxr-xr-x]indra/newview/llnavigationbar.h0
-rw-r--r--indra/newview/llpanelgroup.cpp34
-rw-r--r--indra/newview/llpanelgroup.h9
-rw-r--r--indra/newview/llpanellogin.cpp36
-rw-r--r--indra/newview/llpanellogin.h6
-rw-r--r--indra/newview/llpanelobject.cpp37
-rw-r--r--indra/newview/llpanelvolume.cpp10
-rw-r--r--indra/newview/llpreviewnotecard.cpp7
-rw-r--r--indra/newview/llpreviewscript.cpp4
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp1
-rw-r--r--indra/newview/llspatialpartition.cpp5
-rw-r--r--indra/newview/llspatialpartition.h2
-rw-r--r--indra/newview/llstartup.cpp6
-rw-r--r--indra/newview/lltexturecache.cpp119
-rw-r--r--indra/newview/lltexturecache.h3
-rw-r--r--indra/newview/lltoolbarview.cpp2
-rw-r--r--indra/newview/lltooldraganddrop.cpp2
-rw-r--r--indra/newview/lltoolselect.cpp9
-rw-r--r--indra/newview/llviewerassetstorage.cpp4
-rw-r--r--indra/newview/llviewerassetupload.cpp39
-rw-r--r--indra/newview/llvieweraudio.cpp59
-rw-r--r--indra/newview/llviewercontrol.cpp12
-rw-r--r--indra/newview/llviewerdisplay.cpp5
-rw-r--r--indra/newview/llviewerinput.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp19
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llviewermenufile.cpp2
-rw-r--r--indra/newview/llviewerobject.cpp168
-rw-r--r--indra/newview/llviewerobject.h64
-rw-r--r--indra/newview/llviewerobjectlist.cpp3
-rw-r--r--indra/newview/llvieweroctree.h1
-rw-r--r--indra/newview/llviewerparcelmgr.cpp3
-rw-r--r--[-rwxr-xr-x]indra/newview/llviewerparceloverlay.cpp235
-rw-r--r--indra/newview/llviewerparceloverlay.h5
-rw-r--r--[-rwxr-xr-x]indra/newview/llviewerregion.cpp0
-rw-r--r--indra/newview/llviewerstatsrecorder.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp55
-rw-r--r--indra/newview/llvocache.cpp6
-rw-r--r--indra/newview/llvoicevivox.cpp3
-rw-r--r--indra/newview/llvoicewebrtc.cpp14
-rw-r--r--indra/newview/llvovolume.cpp153
-rw-r--r--indra/newview/llvovolume.h5
-rw-r--r--indra/newview/llvowlsky.cpp7
-rw-r--r--indra/newview/llwatchdog.cpp1
-rw-r--r--indra/newview/llweb.cpp13
-rw-r--r--indra/newview/llworldmap.cpp1
-rw-r--r--[-rwxr-xr-x]indra/newview/llworldmapview.cpp40
-rw-r--r--indra/newview/pipeline.cpp17
-rw-r--r--[-rwxr-xr-x]indra/newview/res/have_artwork_bundle.marker0
-rw-r--r--[-rwxr-xr-x]indra/newview/res/viewerRes.rc0
-rw-r--r--[-rwxr-xr-x]indra/newview/secondlife-i686.supp0
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml24
-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--[-rwxr-xr-x]indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml0
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml4
-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
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_local.xml20
-rw-r--r--indra/test/namedtempfile.h45
-rw-r--r--indra/test/test.cpp6
-rwxr-xr-x[-rw-r--r--]scripts/code_tools/fix_whitespace.py0
-rwxr-xr-x[-rw-r--r--]scripts/code_tools/fix_xml_indentations.py0
-rwxr-xr-x[-rw-r--r--]scripts/code_tools/modified-strings.sh0
-rwxr-xr-x[-rw-r--r--]scripts/code_tools/modified_strings.py0
-rwxr-xr-x[-rw-r--r--]scripts/content_tools/anim_tool.py0
-rwxr-xr-x[-rw-r--r--]scripts/content_tools/arche_tool.py0
-rwxr-xr-x[-rw-r--r--]scripts/content_tools/dae_tool.py0
-rwxr-xr-x[-rw-r--r--]scripts/content_tools/skel_tool.py0
-rw-r--r--[-rwxr-xr-x]scripts/messages/message_template.msg0
-rw-r--r--[-rwxr-xr-x]scripts/messages/message_template.msg.sha10
-rwxr-xr-x[-rw-r--r--]scripts/metrics/slp_conv.py0
-rwxr-xr-x[-rw-r--r--]scripts/metrics/viewer_asset_logs.py0
-rwxr-xr-x[-rw-r--r--]scripts/perf/logsdir.py0
-rwxr-xr-x[-rw-r--r--]scripts/perf/perfbot_run.py0
-rwxr-xr-x[-rw-r--r--]scripts/perf/profile_cmp.py0
-rwxr-xr-x[-rw-r--r--]scripts/perf/profile_csv.py0
-rwxr-xr-x[-rw-r--r--]scripts/perf/profile_pretty.py0
-rw-r--r--[-rwxr-xr-x]scripts/templates/template-cpp.cpp0
-rw-r--r--[-rwxr-xr-x]scripts/templates/template-h.h0
256 files changed, 3883 insertions, 3523 deletions
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index b6b3ba55ac..01071d1377 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -87,7 +87,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 }}
@@ -110,14 +110,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
@@ -127,7 +127,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 }}-${{ matrix.build_variant }}-${{ hashFiles('autobuild.xml') }}
@@ -412,13 +412,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
@@ -451,7 +451,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
@@ -473,15 +473,15 @@ jobs:
runs-on: ubuntu-latest
if: needs.setup.outputs.release_run
steps:
- - uses: actions/download-artifact@v5
+ - uses: actions/download-artifact@v7
with:
pattern: "*-installer"
- - uses: actions/download-artifact@v5
+ - uses: actions/download-artifact@v7
with:
pattern: "*-metadata"
- - uses: actions/download-artifact@v5
+ - uses: actions/download-artifact@v7
with:
name: "Linux-app"
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/.gitignore b/.gitignore
index a784d6e7d4..a784d6e7d4 100755..100644
--- a/.gitignore
+++ b/.gitignore
diff --git a/LICENSE b/LICENSE
index 4362b49151..4362b49151 100755..100644
--- a/LICENSE
+++ b/LICENSE
diff --git a/doc/LGPL-license.txt b/doc/LGPL-license.txt
index 4362b49151..4362b49151 100755..100644
--- a/doc/LGPL-license.txt
+++ b/doc/LGPL-license.txt
diff --git a/doc/LICENSE-logos.txt b/doc/LICENSE-logos.txt
index 66f8745f4f..66f8745f4f 100755..100644
--- a/doc/LICENSE-logos.txt
+++ b/doc/LICENSE-logos.txt
diff --git a/doc/LICENSE-source.txt b/doc/LICENSE-source.txt
index 3de5123415..3de5123415 100755..100644
--- a/doc/LICENSE-source.txt
+++ b/doc/LICENSE-source.txt
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 1f911a8b39..1f911a8b39 100755..100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
diff --git a/doc/releasenotes-where.txt b/doc/releasenotes-where.txt
index 4af5866905..4af5866905 100755..100644
--- a/doc/releasenotes-where.txt
+++ b/doc/releasenotes-where.txt
diff --git a/doc/translations.txt b/doc/translations.txt
index 9b7f2d6292..9b7f2d6292 100755..100644
--- a/doc/translations.txt
+++ b/doc/translations.txt
diff --git a/indra/lib/python/indra/__init__.py b/indra/lib/python/indra/__init__.py
index 0c5053cf49..0c5053cf49 100755..100644
--- a/indra/lib/python/indra/__init__.py
+++ b/indra/lib/python/indra/__init__.py
diff --git a/indra/lib/python/indra/ipc/__init__.py b/indra/lib/python/indra/ipc/__init__.py
index 302bbf4a03..302bbf4a03 100755..100644
--- a/indra/lib/python/indra/ipc/__init__.py
+++ b/indra/lib/python/indra/ipc/__init__.py
diff --git a/indra/lib/python/indra/ipc/compatibility.py b/indra/lib/python/indra/ipc/compatibility.py
index d6ab4f15d5..d6ab4f15d5 100755..100644
--- a/indra/lib/python/indra/ipc/compatibility.py
+++ b/indra/lib/python/indra/ipc/compatibility.py
diff --git a/indra/lib/python/indra/ipc/llmessage.py b/indra/lib/python/indra/ipc/llmessage.py
index 235729944c..235729944c 100755..100644
--- a/indra/lib/python/indra/ipc/llmessage.py
+++ b/indra/lib/python/indra/ipc/llmessage.py
diff --git a/indra/lib/python/indra/ipc/tokenstream.py b/indra/lib/python/indra/ipc/tokenstream.py
index a8e0a17e9c..a8e0a17e9c 100755..100644
--- a/indra/lib/python/indra/ipc/tokenstream.py
+++ b/indra/lib/python/indra/ipc/tokenstream.py
diff --git a/indra/lib/python/indra/util/__init__.py b/indra/lib/python/indra/util/__init__.py
index b004e5804f..b004e5804f 100755..100644
--- a/indra/lib/python/indra/util/__init__.py
+++ b/indra/lib/python/indra/util/__init__.py
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index 1bd65eb57d..1bd65eb57d 100755..100644
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp
index d5323e0b84..45f51950ec 100644
--- a/indra/llappearance/llpolymesh.cpp
+++ b/indra/llappearance/llpolymesh.cpp
@@ -280,7 +280,7 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName )
LL_ERRS() << "Filename is Empty!" << LL_ENDL;
return false;
}
- LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/
+ LLFILE* fp = LLFile::fopen(fileName, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!fp)
{
LLError::LLUserWarningMsg::showMissingFiles();
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index 1bdaa814b7..5a02dfe716 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1449,6 +1449,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
@@ -1458,6 +1464,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)
{
@@ -1494,6 +1506,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/llappearanceutility/llappappearanceutility.cpp b/indra/llappearanceutility/llappappearanceutility.cpp
index d223c859ab..cdc9cfdf40 100644
--- a/indra/llappearanceutility/llappappearanceutility.cpp
+++ b/indra/llappearanceutility/llappappearanceutility.cpp
@@ -57,6 +57,8 @@
#include "llprocesstexture.h"
#include "llprocessskin.h"
+#include "apr_getopt.h"
+
const std::string NOTHING_EXTRA("");
////////////////////////////////////////////
diff --git a/indra/llappearanceutility/llprocessparams.cpp b/indra/llappearanceutility/llprocessparams.cpp
index ad1b44e794..ad1b44e794 100755..100644
--- a/indra/llappearanceutility/llprocessparams.cpp
+++ b/indra/llappearanceutility/llprocessparams.cpp
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index d8a6fffea6..232b429130 100755..100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -199,7 +199,7 @@ bool LLVorbisDecodeState::initDecode()
LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL;
mInFilep = new LLFileSystem(mUUID, LLAssetType::AT_SOUND);
- if (!mInFilep || !mInFilep->getSize())
+ if (!mInFilep || mInFilep->getSize() <= 0)
{
LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL;
delete mInFilep;
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index a9a229c0a5..a9a229c0a5 100755..100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt
index 0d7802279a..9dbbddde8a 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/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index be1c74a908..4e5a920230 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -589,7 +589,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
}
else
{
- LL_WARNS() << "Failed to allocate buffer: " << anim_file_size << mID << LL_ENDL;
+ LL_WARNS() << "Failed to allocate buffer: " << anim_file_size << " " << mID << LL_ENDL;
}
delete anim_file;
anim_file = NULL;
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 b41ffb6dbf..deb3a26ead 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -67,6 +67,7 @@ set(llcommon_SOURCE_FILES
llmetricperformancetester.cpp
llmortician.cpp
llmutex.cpp
+ llpointer.cpp
llptrto.cpp
llpredicate.cpp
llprocess.cpp
@@ -322,6 +323,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lleventfilter "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llevents "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llfile "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llhttpdate "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llheteromap "" "${test_libs}")
diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h
index 2c900c02a7..237d99ae86 100644
--- a/indra/llcommon/fsyspath.h
+++ b/indra/llcommon/fsyspath.h
@@ -57,7 +57,7 @@ class fsyspath: public std::filesystem::path
public:
// default
- fsyspath() {}
+ fsyspath() = default;
// construct from UTF-8 encoded string
fsyspath(const std::string& path): fsyspath(std::string_view(path)) {}
fsyspath(const char* path): fsyspath(std::string_view(path)) {}
@@ -66,8 +66,10 @@ public:
{}
// construct from existing path
fsyspath(const super& path): super(path) {}
+ fsyspath(super&& path) : super(std::move(path)) {}
fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
+ fsyspath& operator=(super&& p) { super::operator=(std::move(p)); return *this; }
fsyspath& operator=(const std::string& p) { return (*this) = std::string_view(p); }
fsyspath& operator=(const char* p) { return (*this) = std::string_view(p); }
fsyspath& operator=(std::string_view p)
diff --git a/indra/llcommon/hexdump.h b/indra/llcommon/hexdump.h
index ab5ba2b16d..ab5ba2b16d 100755..100644
--- a/indra/llcommon/hexdump.h
+++ b/indra/llcommon/hexdump.h
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 73b50d0a50..aa84895fb8 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -37,7 +37,7 @@
#endif
#include "llcommon.h"
-#include "llapr.h"
+
#include "llerrorcontrol.h"
#include "llframetimer.h"
#include "lllivefile.h"
@@ -53,6 +53,8 @@
//
// Signal handling
#ifndef LL_WINDOWS
+#include "apr_signal.h"
+
# include <signal.h>
# include <unistd.h> // for fork()
void setup_signals();
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 65ee383c6b..9ea7a34bac 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -526,226 +526,6 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
}
}
-//static
-S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
-{
- LL_PROFILE_ZONE_SCOPED;
- //*****************************************
- LLAPRFilePoolScope scope(pool);
- apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
- //*****************************************
- if (!file_handle)
- {
- return 0;
- }
-
- llassert(offset >= 0);
-
- if (offset > 0)
- offset = LLAPRFile::seek(file_handle, APR_SET, offset);
-
- apr_size_t bytes_read;
- if (offset < 0)
- {
- bytes_read = 0;
- }
- else
- {
- bytes_read = nbytes ;
- apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
- if (s != APR_SUCCESS)
- {
- LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
- ll_apr_warn_status(s);
- bytes_read = 0;
- }
- else
- {
- llassert_always(bytes_read <= 0x7fffffff);
- }
- }
-
- //*****************************************
- close(file_handle) ;
- //*****************************************
- return (S32)bytes_read;
-}
-
-//static
-S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
-{
- LL_PROFILE_ZONE_SCOPED;
- apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
- if (offset < 0)
- {
- flags |= APR_APPEND;
- offset = 0;
- }
-
- //*****************************************
- LLAPRFilePoolScope scope(pool);
- apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);
- //*****************************************
- if (!file_handle)
- {
- return 0;
- }
-
- if (offset > 0)
- {
- offset = LLAPRFile::seek(file_handle, APR_SET, offset);
- }
-
- apr_size_t bytes_written;
- if (offset < 0)
- {
- bytes_written = 0;
- }
- else
- {
- bytes_written = nbytes ;
- apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
- if (s != APR_SUCCESS)
- {
- LL_WARNS("APR") << "Attempting to write filename: " << filename << LL_ENDL;
- if (APR_STATUS_IS_ENOSPC(s))
- {
- LLApp::notifyOutOfDiskSpace();
- }
- ll_apr_warn_status(s);
- bytes_written = 0;
- }
- else
- {
- llassert_always(bytes_written <= 0x7fffffff);
- }
- }
-
- //*****************************************
- LLAPRFile::close(file_handle);
- //*****************************************
-
- return (S32)bytes_written;
-}
-
-//static
-bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
- return false;
- }
- return true;
-}
-
-//static
-bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
- return false;
- }
- return true;
-}
-
-//static
-bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
-{
- apr_file_t* apr_file;
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS || !apr_file)
- {
- return false;
- }
- else
- {
- apr_file_close(apr_file) ;
- return true;
- }
-}
-
-//static
-S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
-{
- apr_file_t* apr_file;
- apr_finfo_t info;
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS || !apr_file)
- {
- return 0;
- }
- else
- {
- apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
-
- apr_file_close(apr_file) ;
-
- if (s == APR_SUCCESS)
- {
- return (S32)info.size;
- }
- else
- {
- return 0;
- }
- }
-}
-
-//static
-bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
- return false;
- }
- return true;
-}
-
-//static
-bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
- return false;
- }
- return true;
-}
//
//end of static components of LLAPRFile
//*******************************************************************************************************************************
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 0e1e4277e7..8795a0f2c4 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -35,10 +35,6 @@
#include "llwin32headers.h"
#include "apr_thread_proc.h"
-#include "apr_getopt.h"
-#include "apr_signal.h"
-
-#include "llstring.h"
#include <mutex>
@@ -184,20 +180,7 @@ private:
static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags);
static apr_status_t close(apr_file_t* file) ;
static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
-public:
- // returns false if failure:
- static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
- static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
- static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
- static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
- static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
- static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
-
- // Returns bytes read/written, 0 if read/write fails:
- static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
- static S32 writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
//*******************************************************************************************************************************
};
-
#endif // LL_LLAPR_H
diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp
index d79d06e2a2..33bf01a29b 100644
--- a/indra/llcommon/llcrc.cpp
+++ b/indra/llcommon/llcrc.cpp
@@ -166,7 +166,7 @@ void LLCRC::update(const std::string& filename)
return;
}
- FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
+ FILE* fp = LLFile::fopen(filename, LLFILE_MODE("rb")); /* Flawfinder: ignore */
if (fp)
{
diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h
index a3bde47780..2ea5fbc3b0 100644
--- a/indra/llcommon/llcrc.h
+++ b/indra/llcommon/llcrc.h
@@ -36,7 +36,7 @@
// example (don't try this at work kids):
//
// LLCRC crc;
-// FILE* fp = LLFile::fopen(filename,"rb");
+// FILE* fp = LLFile::fopen(filename,LLFILE_MODE("rb"));
// while(!feof(fp)) {
// crc.update(fgetc(fp));
// }
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 8ae0fabcc6..5b42c83a14 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -481,13 +481,9 @@ namespace
std::string file = user_dir + "/logcontrol-dev.xml";
- llstat stat_info;
- if (LLFile::stat(file, &stat_info)) {
- // NB: stat returns non-zero if it can't read the file, for example
- // if it doesn't exist. LLFile has no better abstraction for
- // testing for file existence.
-
- file = app_dir + "/logcontrol.xml";
+ if (!LLFile::isfile(file))
+ {
+ file = app_dir + "/logcontrol.xml";
}
return * new LogControlFile(file);
// NB: This instance is never freed
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index a539e4fe28..114df29f6e 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -29,22 +29,17 @@
#include "linden_common.h"
#include "llfile.h"
-#include "llstring.h"
#include "llerror.h"
#include "stringize.h"
#if LL_WINDOWS
-#include "llwin32headers.h"
-#include <vector>
+#include <fcntl.h>
#else
#include <errno.h>
+#include <sys/file.h>
#endif
-using namespace std;
-
-static std::string empty;
-
-// Many of the methods below use OS-level functions that mess with errno. Wrap
+// Some of the methods below use OS-level functions that mess with errno. Wrap
// variants of strerror() to report errors.
#if LL_WINDOWS
@@ -79,6 +74,7 @@ static errentry const errtable[]
{ ERROR_CURRENT_DIRECTORY, EACCES }, // 16
{ ERROR_NOT_SAME_DEVICE, EXDEV }, // 17
{ ERROR_NO_MORE_FILES, ENOENT }, // 18
+ { ERROR_SHARING_VIOLATION, EACCES }, // 32
{ ERROR_LOCK_VIOLATION, EACCES }, // 33
{ ERROR_BAD_NETPATH, ENOENT }, // 53
{ ERROR_NETWORK_ACCESS_DENIED, EACCES }, // 65
@@ -109,22 +105,25 @@ static errentry const errtable[]
{ ERROR_NOT_ENOUGH_QUOTA, ENOMEM } // 1816
};
-static int set_errno_from_oserror(unsigned long oserr)
+static int get_errno_from_oserror(int oserr)
{
if (!oserr)
return 0;
// Check the table for the Windows OS error code
- for (const struct errentry &entry : errtable)
+ for (const struct errentry& entry : errtable)
{
if (oserr == entry.oserr)
{
- _set_errno(entry.errcode);
- return -1;
+ return entry.errcode;
}
}
+ return EINVAL;
+}
- _set_errno(EINVAL);
+static int set_errno_from_oserror(unsigned long oserr)
+{
+ _set_errno(get_errno_from_oserror(oserr));
return -1;
}
@@ -136,69 +135,8 @@ std::string strerr(int errn)
return buffer;
}
-inline bool is_slash(wchar_t const c)
-{
- return c == L'\\' || c == L'/';
-}
-
-static std::wstring utf8path_to_wstring(const std::string& utf8path)
-{
- if (utf8path.size() >= MAX_PATH)
- {
- // By prepending "\\?\" to a path, Windows widechar file APIs will not fail on long path names
- std::wstring utf16path = L"\\\\?\\" + ll_convert<std::wstring>(utf8path);
- // We need to make sure that the path does not contain forward slashes as above
- // prefix does bypass the path normalization that replaces slashes with backslashes
- // before passing the path to kernel mode APIs
- std::replace(utf16path.begin(), utf16path.end(), L'/', L'\\');
- return utf16path;
- }
- return ll_convert<std::wstring>(utf8path);
-}
-
-static unsigned short get_fileattr(const std::wstring& utf16path, bool dontFollowSymLink = false)
-{
- unsigned long flags = FILE_FLAG_BACKUP_SEMANTICS;
- if (dontFollowSymLink)
- {
- flags |= FILE_FLAG_OPEN_REPARSE_POINT;
- }
- HANDLE file_handle = CreateFileW(utf16path.c_str(), FILE_READ_ATTRIBUTES,
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
- nullptr, OPEN_EXISTING, flags, nullptr);
- if (file_handle != INVALID_HANDLE_VALUE)
- {
- FILE_ATTRIBUTE_TAG_INFO attribute_info;
- if (GetFileInformationByHandleEx(file_handle, FileAttributeTagInfo, &attribute_info, sizeof(attribute_info)))
- {
- // A volume path alone (only drive letter) is not recognized as directory while it technically is
- bool is_directory = (attribute_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
- (iswalpha(utf16path[0]) && utf16path[1] == ':' &&
- (!utf16path[2] || (is_slash(utf16path[2]) && !utf16path[3])));
- unsigned short st_mode = is_directory ? S_IFDIR :
- (attribute_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? S_IFLNK : S_IFREG);
- st_mode |= (attribute_info.FileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD | S_IWRITE;
- // we do not try to guess executable flag
-
- // propagate user bits to group/other fields:
- st_mode |= (st_mode & 0700) >> 3;
- st_mode |= (st_mode & 0700) >> 6;
-
- CloseHandle(file_handle);
- return st_mode;
- }
- }
- // Retrieve last error and set errno before calling CloseHandle()
- set_errno_from_oserror(GetLastError());
-
- if (file_handle != INVALID_HANDLE_VALUE)
- {
- CloseHandle(file_handle);
- }
- return 0;
-}
-
#else
+
// On Posix we want to call strerror_r(), but alarmingly, there are two
// different variants. The one that returns int always populates the passed
// buffer (except in case of error), whereas the other one always returns a
@@ -245,9 +183,50 @@ std::string strerr(int errn)
return message_from(errn, buffer, sizeof(buffer),
strerror_r(errn, buffer, sizeof(buffer)));
}
+
#endif // ! LL_WINDOWS
-static int warnif(const std::string& desc, const std::string& filename, int rc, int accept = 0)
+#if LL_WINDOWS && 0 // turn on to debug file-locking problems
+#define PROCESS_LOCKING_CHECK 1
+static void find_locking_process(const std::string& filename)
+{
+ // Only do any of this stuff (before LL_ENDL) if it will be logged.
+ LL_DEBUGS("LLFile") << "";
+ // wrong way
+ std::string TEMP = LLFile::tmpdir();
+ if (TEMP.empty())
+ {
+ LL_CONT << "No $TEMP, not running 'handle'";
+ }
+ else
+ {
+ std::string tf(TEMP);
+ tf += "handle.tmp";
+ // http://technet.microsoft.com/en-us/sysinternals/bb896655
+ std::string cmd(STRINGIZE("handle \"" << filename
+ // "openfiles /query /v | fgrep -i \"" << filename
+ << "\" > \"" << tf << '"'));
+ LL_CONT << cmd;
+ if (system(cmd.c_str()) != 0)
+ {
+ LL_CONT << "\nDownload 'handle.exe' from http://technet.microsoft.com/en-us/sysinternals/bb896655";
+ }
+ else
+ {
+ std::ifstream inf(tf);
+ std::string line;
+ while (std::getline(inf, line))
+ {
+ LL_CONT << '\n' << line;
+ }
+ }
+ LLFile::remove(tf);
+ }
+ LL_CONT << LL_ENDL;
+}
+#endif // LL_WINDOWS hack to identify processes holding file open
+
+static int warnif(std::string_view desc, const std::filesystem::path& filename, int rc, int suppress_warning = 0)
{
if (rc < 0)
{
@@ -256,322 +235,840 @@ static int warnif(const std::string& desc, const std::string& filename, int rc,
// For certain operations, a particular errno value might be
// acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit
- // EEXIST. Don't warn if caller explicitly says this errno is okay.
- if (errn != accept)
+ // EEXIST. Don't log a warning if caller explicitly says this errno is okay.
+ if (errn != suppress_warning)
{
- LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename
- << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL;
+ LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL;
}
-#if 0 && LL_WINDOWS // turn on to debug file-locking problems
+#if PROCESS_LOCKING_CHECK
// If the problem is "Permission denied," maybe it's because another
// process has the file open. Try to find out.
- if (errn == EACCES) // *not* EPERM
+ if (errn == EACCES) // *not* EPERM
{
- // Only do any of this stuff (before LL_ENDL) if it will be logged.
- LL_DEBUGS("LLFile") << empty;
- // would be nice to use LLDir for this, but dependency goes the
- // wrong way
- const char* TEMP = LLFile::tmpdir();
- if (! (TEMP && *TEMP))
- {
- LL_CONT << "No $TEMP, not running 'handle'";
- }
- else
- {
- std::string tf(TEMP);
- tf += "\\handle.tmp";
- // http://technet.microsoft.com/en-us/sysinternals/bb896655
- std::string cmd(STRINGIZE("handle \"" << filename
- // "openfiles /query /v | fgrep -i \"" << filename
- << "\" > \"" << tf << '"'));
- LL_CONT << cmd;
- if (system(cmd.c_str()) != 0)
- {
- LL_CONT << "\nDownload 'handle.exe' from http://technet.microsoft.com/en-us/sysinternals/bb896655";
- }
- else
- {
- std::ifstream inf(tf);
- std::string line;
- while (std::getline(inf, line))
- {
- LL_CONT << '\n' << line;
- }
- }
- LLFile::remove(tf);
- }
- LL_CONT << LL_ENDL;
+ find_locking_process(filename);
}
-#endif // LL_WINDOWS hack to identify processes holding file open
+#endif
}
return rc;
}
-// static
-int LLFile::mkdir(const std::string& dirname, int perms)
+static int warnif(std::string_view desc, const std::filesystem::path& filename, const std::error_code& ec, int suppress_warning = 0)
{
- // We often use mkdir() to ensure the existence of a directory that might
- // already exist. There is no known case in which we want to call out as
- // an error the requested directory already existing.
+ if (ec)
+ {
+ // get Posix errno from the std::error_code so we can compare it to the suppress_warning parameter
+ // to see when a caller wants us to not generate a warning for a particular error code
#if LL_WINDOWS
- // permissions are ignored on Windows
- int rc = 0;
- std::wstring utf16dirname = utf8path_to_wstring(dirname);
- if (!CreateDirectoryW(utf16dirname.c_str(), nullptr))
+ int errn = get_errno_from_oserror(ec.value());
+#else
+ int errn = ec.value();
+#endif
+ // For certain operations, a particular errno value might be acceptable
+ // Don't warn if caller explicitly says this errno is okay.
+ if (errn != suppress_warning)
+ {
+ LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename << "' (errno " << errn << "): " << ec.message() << LL_ENDL;
+ }
+#if PROCESS_LOCKING_CHECK
+ // Try to detect locked files by other processes
+ if (ec.value() == ERROR_SHARING_VIOLATION || ec.value() == ERROR_LOCK_VIOLATION)
+ {
+ find_locking_process(filename);
+ }
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+#if LL_WINDOWS
+
+inline int set_ec_from_system_error(std::error_code& ec, DWORD error)
+{
+ ec.assign(error, std::system_category());
+ return -1;
+}
+
+static int set_ec_from_system_error(std::error_code& ec)
+{
+ return set_ec_from_system_error(ec, GetLastError());
+}
+
+inline int set_ec_to_parameter_error(std::error_code& ec)
+{
+ return set_ec_from_system_error(ec, ERROR_INVALID_PARAMETER);
+}
+
+inline int set_ec_to_outofmemory_error(std::error_code& ec)
+{
+ return set_ec_from_system_error(ec, ERROR_NOT_ENOUGH_MEMORY);
+}
+
+inline DWORD decode_access_mode(std::ios_base::openmode omode)
+{
+ switch (omode & (LLFile::in | LLFile::out))
{
- // Only treat other errors than an already existing file as a real error
- unsigned long oserr = GetLastError();
- if (oserr != ERROR_ALREADY_EXISTS)
+ case LLFile::in:
+ return GENERIC_READ;
+ case LLFile::out:
+ return GENERIC_WRITE;
+ case static_cast<std::ios_base::openmode>(LLFile::in | LLFile::out):
+ return GENERIC_READ | GENERIC_WRITE;
+ }
+ if (omode & LLFile::app)
+ {
+ return GENERIC_WRITE;
+ }
+ return 0;
+}
+
+inline DWORD decode_open_create_flags(std::ios_base::openmode omode)
+{
+ if (omode & LLFile::noreplace)
+ {
+ return CREATE_NEW; // create if it does not exist, otherwise fail
+ }
+ if (omode & LLFile::trunc)
+ {
+ if (!(omode & LLFile::out))
{
- rc = set_errno_from_oserror(oserr);
+ return TRUNCATE_EXISTING; // open and truncate if it exists, otherwise fail
}
+ return CREATE_ALWAYS; // open and truncate if it exists, otherwise create it
}
+ if (!(omode & LLFile::out))
+ {
+ return OPEN_EXISTING; // open if it exists, otherwise fail
+ }
+ // LLFile::app or (LLFile::out and (!LLFile::trunc or !LLFile::noreplace))
+ return OPEN_ALWAYS; // open if it exists, otherwise create it
+}
+
+inline DWORD decode_share_mode(int omode)
+{
+ if (omode & LLFile::exclusive)
+ {
+ return 0; // allow no other access
+ }
+ if (omode & LLFile::shared)
+ {
+ return FILE_SHARE_READ; // allow read access
+ }
+ return FILE_SHARE_READ | FILE_SHARE_WRITE; // allow read and write access to others
+}
+
+inline DWORD decode_attributes(std::ios_base::openmode omode, int perm)
+{
+ return (perm & S_IWRITE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY;
+}
+
+// Under Windows the values for the std::ios_base::seekdir constants match the according FILE_BEGIN
+// and other constants but we do a programmatic translation for now to be sure
+static DWORD seek_mode_from_dir(std::ios_base::seekdir seekdir)
+{
+ switch (seekdir)
+ {
+ case LLFile::beg:
+ return FILE_BEGIN;
+ case LLFile::cur:
+ return FILE_CURRENT;
+ case LLFile::end:
+ return FILE_END;
+ }
+ return FILE_BEGIN;
+}
+
#else
- int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
- if (rc < 0 && errno == EEXIST)
+
+inline int set_ec_from_system_error(std::error_code& ec, int error)
+{
+ ec.assign(error, std::system_category());
+ return -1;
+}
+
+static int set_ec_from_system_error(std::error_code& ec)
+{
+ return set_ec_from_system_error(ec, errno);
+}
+
+inline int set_ec_to_parameter_error(std::error_code& ec)
+{
+ return set_ec_from_system_error(ec, EINVAL);
+}
+
+inline int set_ec_to_outofmemory_error(std::error_code& ec)
+{
+ return set_ec_from_system_error(ec, ENOMEM);
+}
+
+inline int decode_access_mode(std::ios_base::openmode omode)
+{
+ if (omode & LLFile::out)
{
- // this is not the error you want, move along
- return 0;
+ if (omode & LLFile::in)
+ {
+ return O_RDWR;
+ }
+ return O_WRONLY;
+ }
+ return O_RDONLY;
+
+ /*switch (omode & (LLFile::in | LLFile::out))
+ {
+ case LLFile::out:
+ return O_WRONLY;
+ case static_cast<std::ios_base::openmode>(LLFile::in | LLFile::out):
+ return O_RDWR;
}
+ return O_RDONLY;*/
+}
+
+inline int decode_open_mode(std::ios_base::openmode omode)
+{
+ int flags = O_CREAT | decode_access_mode(omode);
+ if (omode & LLFile::app)
+ {
+ flags |= O_APPEND;
+ }
+ if (omode & LLFile::trunc)
+ {
+ flags |= O_TRUNC;
+ }
+ if (omode & LLFile::binary)
+ {
+ // Not a thing under *nix
+ }
+ if (omode & LLFile::noreplace)
+ {
+ flags |= O_EXCL;
+ }
+ return flags;
+}
+
+inline int decode_lock_mode(std::ios_base::openmode omode)
+{
+ int lmode = omode & LLFile::noblock ? LOCK_NB : 0;
+ if (omode & LLFile::lock_mask)
+ {
+ if (omode & LLFile::exclusive)
+ {
+ return lmode | LOCK_EX;
+ }
+ return lmode | LOCK_SH;
+ }
+ return lmode | LOCK_UN;
+}
+
+// Under Linux and Mac the values for the std::ios_base::seekdir constants match the according SEEK_SET
+// and other constants but we do a programmatic translation for now to be sure
+inline int seek_mode_from_dir(std::ios_base::seekdir seekdir)
+{
+ switch (seekdir)
+ {
+ case LLFile::beg:
+ return SEEK_SET;
+ case LLFile::cur:
+ return SEEK_CUR;
+ case LLFile::end:
+ return SEEK_END;
+ }
+ return SEEK_SET;
+}
+
#endif
- // anything else might be a problem
- return warnif("mkdir", dirname, rc);
+
+inline int clear_error(std::error_code& ec)
+{
+ ec.clear();
+ return 0;
}
-// static
-int LLFile::rmdir(const std::string& dirname, int suppress_error)
+inline bool are_open_mode_flags_invalid(std::ios_base::openmode omode)
+{
+ // at least one of input or output needs to be specified
+ if (!(omode & (LLFile::in | LLFile::out)))
+ {
+ return true;
+ }
+ // output must be possible for any of the extra options
+ if (!(omode & LLFile::out) && (omode & (LLFile::trunc | LLFile::app | LLFile::noreplace)))
+ {
+ return true;
+ }
+ // invalid combination, mutually exclusive
+ if ((omode & LLFile::app) && (omode & (LLFile::trunc | LLFile::noreplace)))
+ {
+ return true;
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------------------
+// class member functions
+//----------------------------------------------------------------------------------------
+int LLFile::open(const std::filesystem::path& file_path, std::ios_base::openmode omode, std::error_code& ec, int perm)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ close(ec);
+ if (are_open_mode_flags_invalid(omode))
+ {
+ return set_ec_to_parameter_error(ec);
+ }
#if LL_WINDOWS
- std::wstring utf16dirname = utf8path_to_wstring(dirname);
- int rc = _wrmdir(utf16dirname.c_str());
+ DWORD access = decode_access_mode(omode),
+ share = decode_share_mode(omode),
+ create = decode_open_create_flags(omode),
+ attributes = decode_attributes(omode, perm);
+
+ mHandle = CreateFileW(file_path.native().c_str(), access, share, nullptr, create, attributes, nullptr);
+ // The dwShareMode = share parameter takes care of locking the file for other processes if indicated,
+ // no need to do anything else for file locking here
#else
- int rc = ::rmdir(dirname.c_str());
+ int oflags = decode_open_mode(omode);
+ int lmode = omode & LLFile::lock_mask;
+ mHandle = ::open(file_path.native().c_str(), oflags, perm);
+ if (mHandle != InvalidHandle && lmode && lock(lmode | LLFile::noblock, ec) != 0)
+ {
+ close();
+ return -1;
+ }
#endif
- return warnif("rmdir", dirname, rc, suppress_error);
+ if (mHandle == InvalidHandle)
+ {
+ return set_ec_from_system_error(ec);
+ }
+
+ if (omode & LLFile::ate && seek(0, LLFile::end, ec) != 0)
+ {
+ close();
+ return -1;
+ }
+ mOpen = omode;
+ return clear_error(ec);
}
-// static
-LLFILE* LLFile::fopen(const std::string& filename, const char* mode)
+S64 LLFile::size(std::error_code& ec)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
#if LL_WINDOWS
- std::wstring utf16filename = utf8path_to_wstring(filename);
- std::wstring utf16mode = ll_convert<std::wstring>(std::string(mode));
- return _wfopen(utf16filename.c_str(), utf16mode.c_str());
+ LARGE_INTEGER value = { 0 };
+ if (GetFileSizeEx(mHandle, &value))
+ {
+ clear_error(ec);
+ return value.QuadPart;
+ }
#else
- return ::fopen(filename.c_str(),mode);
+ struct stat statval;
+ if (fstat(mHandle, &statval) == 0)
+ {
+ clear_error(ec);
+ return statval.st_size;
+ }
#endif
+ set_ec_from_system_error(ec);
+ return 0;
}
-// static
-int LLFile::close(LLFILE * file)
+S64 LLFile::tell(std::error_code& ec)
{
- int ret_value = 0;
- if (file)
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+#if LL_WINDOWS
+ LARGE_INTEGER value = { 0 };
+ if (SetFilePointerEx(mHandle, value, &value, FILE_CURRENT))
{
- ret_value = fclose(file);
+ clear_error(ec);
+ return value.QuadPart;
}
- return ret_value;
+#else
+ off_t offset = lseek(mHandle, 0, SEEK_CUR);
+ if (offset != -1)
+ {
+ clear_error(ec);
+ return offset;
+ }
+#endif
+ return set_ec_from_system_error(ec);
}
-// static
-std::string LLFile::getContents(const std::string& filename)
+int LLFile::seek(S64 pos, std::error_code& ec)
{
- LLFILE* fp = LLFile::fopen(filename, "rb");
- if (fp)
+ return seek(pos, LLFile::beg, ec);
+}
+
+int LLFile::seek(S64 offset, std::ios_base::seekdir dir, std::error_code& ec)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ S64 newOffset = 0;
+#if LL_WINDOWS
+ DWORD seekdir = seek_mode_from_dir(dir);
+ LARGE_INTEGER value;
+ value.QuadPart = offset;
+ if (SetFilePointerEx(mHandle, value, (PLARGE_INTEGER)&newOffset, seekdir))
+#else
+ newOffset = lseek(mHandle, offset, seek_mode_from_dir(dir));
+ if (newOffset != -1)
+#endif
{
- fseek(fp, 0, SEEK_END);
- U32 length = ftell(fp);
- fseek(fp, 0, SEEK_SET);
+ return clear_error(ec);
+ }
+ return set_ec_from_system_error(ec);
+}
- std::vector<char> buffer(length);
- size_t nread = fread(buffer.data(), 1, length, fp);
- fclose(fp);
+#if LL_WINDOWS
+inline DWORD next_buffer_size(S64 nbytes)
+{
+ return nbytes > 0x80000000 ? 0x80000000 : (DWORD)nbytes;
+}
+#endif
- return std::string(buffer.data(), nread);
+S64 LLFile::read(void* buffer, S64 nbytes, std::error_code& ec)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ if (nbytes == 0)
+ {
+ // Nothing to do
+ return clear_error(ec);
}
+ else if (!buffer || nbytes < 0)
+ {
+ return set_ec_to_parameter_error(ec);
+ }
+#if LL_WINDOWS
+ S64 totalBytes = 0;
+ char *ptr = (char*)buffer;
+ DWORD bytesRead, bytesToRead = next_buffer_size(nbytes);
- return LLStringUtil::null;
+ // Read in chunks to support >4GB which the S64 nbytes value makes possible
+ while (ReadFile(mHandle, ptr, bytesToRead, &bytesRead, nullptr))
+ {
+ totalBytes += bytesRead;
+ if (nbytes <= totalBytes || // requested amount read
+ bytesRead < bytesToRead) // ReadFile encountered eof
+ {
+ clear_error(ec);
+ return totalBytes;
+ }
+ ptr += bytesRead;
+ bytesToRead = next_buffer_size(nbytes - totalBytes);
+ }
+#else
+ ssize_t bytesRead = ::read(mHandle, buffer, nbytes);
+ if (bytesRead != -1)
+ {
+ clear_error(ec);
+ return bytesRead;
+ }
+#endif
+ return set_ec_from_system_error(ec);
}
-// static
-int LLFile::remove(const std::string& filename, int suppress_error)
+S64 LLFile::write(const void* buffer, S64 nbytes, std::error_code& ec)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ if (nbytes == 0)
+ {
+ // Nothing to do here
+ return clear_error(ec);
+ }
+ else if (!buffer || nbytes < 0)
+ {
+ return set_ec_to_parameter_error(ec);
+ }
#if LL_WINDOWS
- // Posix remove() works on both files and directories although on Windows
- // remove() and its wide char variant _wremove() only removes files just
- // as its siblings unlink() and _wunlink().
- // If we really only want to support files we should instead use
- // unlink() in the non-Windows part below too
- int rc = -1;
- std::wstring utf16filename = utf8path_to_wstring(filename);
- unsigned short st_mode = get_fileattr(utf16filename);
- if (S_ISDIR(st_mode))
+ // If this was opened in append mode, we emulate it on Windows
+ if (mOpen & LLFile::app && seek(0, LLFile::end, ec) != 0)
{
- rc = _wrmdir(utf16filename.c_str());
+ return -1;
}
- else if (S_ISREG(st_mode))
+
+ S64 totalBytes = 0;
+ char* ptr = (char*)buffer;
+ DWORD bytesWritten, bytesToWrite = next_buffer_size(nbytes);
+
+ // Write in chunks to support >4GB which the S64 nbytes value makes possible
+ while (WriteFile(mHandle, ptr, bytesToWrite, &bytesWritten, nullptr))
{
- rc = _wunlink(utf16filename.c_str());
+ totalBytes += bytesWritten;
+ if (nbytes <= totalBytes)
+ {
+ clear_error(ec);
+ return totalBytes;
+ }
+ ptr += bytesWritten;
+ bytesToWrite = next_buffer_size(nbytes - totalBytes);
}
- else if (st_mode)
+#else
+ ssize_t bytesWritten = ::write(mHandle, buffer, nbytes);
+ if (bytesWritten != -1)
{
- // it is something else than a file or directory
- // this should not really happen as long as we do not allow for symlink
- // detection in the optional parameter to get_fileattr()
- rc = set_errno_from_oserror(ERROR_INVALID_PARAMETER);
+ clear_error(ec);
+ return bytesWritten;
+ }
+#endif
+ return set_ec_from_system_error(ec);
+}
+
+S64 LLFile::printf(const char* fmt, ...)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ va_list args1;
+ va_start(args1, fmt);
+ va_list args2;
+ va_copy(args2, args1);
+ int length = vsnprintf(nullptr, 0, fmt, args1);
+ va_end(args1);
+ if (length < 0)
+ {
+ va_end(args2);
+ return -1;
+ }
+ void* buffer = malloc(length + 1);
+ if (!buffer)
+ {
+ va_end(args2);
+ return -1;
+ }
+ length = vsnprintf((char*)buffer, length + 1, fmt, args2);
+ va_end(args2);
+ std::error_code ec;
+ S64 written = write(buffer, length, ec);
+ free(buffer);
+ return written;
+}
+
+int LLFile::lock(int mode, std::error_code& ec)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+#if LL_WINDOWS
+ if (!(mode & LLFile::lock_mask))
+ {
+ if (UnlockFile(mHandle, 0, 0, MAXDWORD, MAXDWORD))
+ {
+ return clear_error(ec);
+ }
}
else
{
- // get_fileattr() failed and already set errno, preserve it for correct error reporting
+ OVERLAPPED overlapped = { 0 };
+ DWORD flags = (mode & LLFile::noblock) ? LOCKFILE_FAIL_IMMEDIATELY : 0;
+ if (mode & LLFile::exclusive)
+ {
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ // We lock the maximum range, since flock only supports locking the entire file too
+ if (LockFileEx(mHandle, flags, 0, MAXDWORD, MAXDWORD, &overlapped))
+ {
+ return clear_error(ec);
+ }
}
#else
- int rc = ::remove(filename.c_str());
+ if (flock(mHandle, decode_lock_mode(static_cast<std::ios_base::openmode>(mode))) == 0)
+ {
+ return clear_error(ec);
+ }
#endif
- return warnif("remove", filename, rc, suppress_error);
+ return set_ec_from_system_error(ec);
}
+int LLFile::close(std::error_code& ec)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ if (mHandle != InvalidHandle)
+ {
+ llfile_handle_t handle = InvalidHandle;
+ std::swap(handle, mHandle);
+#if LL_WINDOWS
+ if (!CloseHandle(handle))
+#else
+ if (::close(handle))
+#endif
+ {
+ return set_ec_from_system_error(ec);
+ }
+ }
+ return clear_error(ec);
+}
+
+int LLFile::close()
+{
+ std::error_code ec;
+ return close(ec);
+}
+
+//----------------------------------------------------------------------------------------
+// static member functions
+//----------------------------------------------------------------------------------------
+
// static
-int LLFile::rename(const std::string& filename, const std::string& newname, int suppress_error)
+LLFILE* LLFile::fopen(const std::filesystem::path& file_path, const fopen_flags_t* mode, int lmode)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ LLFILE* file;
#if LL_WINDOWS
- // Posix rename() will gladly overwrite a file at newname if it exists, the Windows
- // rename(), respectively _wrename(), will bark on that. Instead call directly the Windows
- // API MoveFileEx() and use its flags to specify that overwrite is allowed.
- std::wstring utf16filename = utf8path_to_wstring(filename);
- std::wstring utf16newname = utf8path_to_wstring(newname);
- int rc = 0;
- if (!MoveFileExW(utf16filename.c_str(), utf16newname.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
+ int shflag = _SH_DENYNO;
+ switch (lmode)
{
- rc = set_errno_from_oserror(GetLastError());
+ case LLFile::exclusive:
+ shflag = _SH_DENYRW;
+ break;
+ case LLFile::shared:
+ shflag = _SH_DENYWR;
+ break;
}
+ file = _wfsopen(file_path.native().c_str(), mode, shflag);
#else
- int rc = ::rename(filename.c_str(),newname.c_str());
+ file = ::fopen(file_path.native().c_str(), mode);
+ if (file && (lmode & (LLFile::lock_mask)))
+ {
+ // Rather fail on a sharing conflict than block
+ if (flock(fileno(file), decode_lock_mode(static_cast<std::ios_base::openmode>(lmode | LLFile::noblock))))
+ {
+ ::fclose(file);
+ file = nullptr;
+ }
+ }
#endif
- return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, suppress_error);
+ return file;
}
-// Make this a define rather than using magic numbers multiple times in the code
-#define LLFILE_COPY_BUFFER_SIZE 16384
+// static
+int LLFile::close(LLFILE* file)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ int ret_value = 0;
+ if (file)
+ {
+ ret_value = ::fclose(file);
+ }
+ return ret_value;
+}
// static
-bool LLFile::copy(const std::string& from, const std::string& to)
+std::string LLFile::getContents(const std::filesystem::path& file_path, std::error_code& ec)
{
- bool copied = false;
- LLFILE* in = LLFile::fopen(from, "rb");
- if (in)
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ std::string buffer;
+ LLFile file(file_path, LLFile::in | LLFile::binary, ec);
+ if (file)
{
- LLFILE* out = LLFile::fopen(to, "wb");
- if (out)
+ S64 length = file.size(ec);
+ if (!ec && length > 0)
{
- char buf[LLFILE_COPY_BUFFER_SIZE];
- size_t readbytes;
- bool write_ok = true;
- while (write_ok && (readbytes = fread(buf, 1, LLFILE_COPY_BUFFER_SIZE, in)))
- {
- if (fwrite(buf, 1, readbytes, out) != readbytes)
- {
- LL_WARNS("LLFile") << "Short write" << LL_ENDL;
- write_ok = false;
- }
- }
- if ( write_ok )
+ buffer = std::string(length, 0);
+ file.read(&buffer[0], length, ec);
+ if (ec)
{
- copied = true;
+ buffer.clear();
}
- fclose(out);
}
- fclose(in);
}
- return copied;
+ return buffer;
}
// static
-int LLFile::stat(const std::string& filename, llstat* filestatus, int suppress_error)
+int LLFile::mkdir(const std::filesystem::path& file_path)
{
-#if LL_WINDOWS
- std::wstring utf16filename = utf8path_to_wstring(filename);
- int rc = _wstat64(utf16filename.c_str(), filestatus);
-#else
- int rc = ::stat(filename.c_str(), filestatus);
-#endif
- return warnif("stat", filename, rc, suppress_error);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ std::error_code ec;
+ // We often use mkdir() to ensure the existence of a directory that might
+ // already exist. There is no known case in which we want to call out as
+ // an error the requested directory already existing.
+ std::filesystem::create_directory(file_path, ec);
+ // The return value is only true if the directory was actually created.
+ // But if it already existed, ec still indicates success.
+ return warnif("mkdir", file_path, ec);
}
// static
-unsigned short LLFile::getattr(const std::string& filename, bool dontFollowSymLink, int suppress_error)
+int LLFile::remove(const std::filesystem::path& file_path, int suppress_warning)
{
-#if LL_WINDOWS
- // _wstat64() is a bit heavyweight on Windows, use a more lightweight API
- // to just get the attributes
- int rc = -1;
- std::wstring utf16filename = utf8path_to_wstring(filename);
- unsigned short st_mode = get_fileattr(utf16filename, dontFollowSymLink);
- if (st_mode)
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ std::error_code ec;
+ std::filesystem::remove(file_path, ec);
+ return warnif("remove", file_path, ec, suppress_warning);
+}
+
+// static
+int LLFile::rename(const std::filesystem::path& file_path, const std::filesystem::path& new_path, int suppress_warning)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ std::error_code ec;
+ std::filesystem::rename(file_path, new_path, ec);
+ return warnif("rename", file_path, ec, suppress_warning);
+}
+
+// static
+S64 LLFile::read(const std::filesystem::path& file_path, void* buf, S64 offset, S64 nbytes, std::error_code& ec)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ // if number of bytes is 0 or less there is nothing to do here
+ if (nbytes <= 0)
{
- return st_mode;
+ clear_error(ec);
+ return 0;
}
-#else
- llstat filestatus;
- int rc = dontFollowSymLink ? ::lstat(filename.c_str(), &filestatus) : ::stat(filename.c_str(), &filestatus);
- if (rc == 0)
+
+ if (!buf || offset < 0)
{
- return filestatus.st_mode;
+ set_ec_to_parameter_error(ec);
}
-#endif
- warnif("getattr", filename, rc, suppress_error);
- return 0;
+ else
+ {
+ std::ios_base::openmode omode = LLFile::in | LLFile::binary;
+
+ LLFile file(file_path, omode, ec);
+ if (!ec && (bool)file)
+ {
+ if (offset > 0)
+ {
+ file.seek(offset, ec);
+ }
+ // else (offset == 0) file was just opened and should already be at 0.
+ if (!ec)
+ {
+ S64 bytes_read = file.read(buf, nbytes, ec);
+ if (!ec)
+ {
+ return bytes_read;
+ }
+ }
+ }
+ }
+ return warnif("read from file failed", file_path, ec);
}
// static
-bool LLFile::isdir(const std::string& filename)
+S64 LLFile::write(const std::filesystem::path& file_path, const void* buf, S64 offset, S64 nbytes, std::error_code& ec)
{
- return S_ISDIR(getattr(filename));
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ // if number of bytes is 0 or less there is nothing to do here
+ if (nbytes <= 0)
+ {
+ clear_error(ec);
+ return 0;
+ }
+
+ if (!buf)
+ {
+ set_ec_to_parameter_error(ec);
+ }
+ else
+ {
+ std::ios_base::openmode omode = LLFile::out | LLFile::binary;
+ if (offset < 0)
+ {
+ omode |= LLFile::app;
+ }
+
+ LLFile file(file_path, omode, ec);
+ if (!ec && (bool)file)
+ {
+ if (offset > 0)
+ {
+ file.seek(offset, ec);
+ }
+ // else (offset == 0) we are not appending, file was just opened and should already be at 0.
+ if (!ec)
+ {
+ S64 bytes_written = file.write(buf, nbytes, ec);
+ if (!ec)
+ {
+ return bytes_written;
+ }
+ }
+ }
+ }
+ return warnif("write to file failed", file_path, ec);
}
// static
-bool LLFile::isfile(const std::string& filename)
+bool LLFile::copy(const std::filesystem::path& source_path, const std::filesystem::path& target_path, std::filesystem::copy_options options, std::error_code& ec)
{
- return S_ISREG(getattr(filename));
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ bool copied = std::filesystem::copy_file(source_path, target_path, options, ec);
+ if (!copied)
+ {
+ warnif(STRINGIZE("copy failed, to '" << target_path << "' from"), source_path, ec);
+ }
+ return copied;
}
// static
-bool LLFile::islink(const std::string& filename)
+int LLFile::stat(const std::filesystem::path& file_path, llstat* filestatus, const char *fname, int suppress_warning)
{
- return S_ISLNK(getattr(filename, true));
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+#if LL_WINDOWS
+ int rc = _wstat64(file_path.native().c_str(), filestatus);
+#else
+ int rc = ::stat(file_path.native().c_str(), filestatus);
+#endif
+ return warnif(fname ? fname : "stat", file_path, rc, suppress_warning);
}
// static
-const char *LLFile::tmpdir()
+S64 LLFile::size(const std::filesystem::path& file_path, int suppress_warning)
{
- static std::string utf8path;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ std::error_code ec;
+ std::intmax_t size = static_cast<std::intmax_t>(std::filesystem::file_size(file_path, ec));
+ if (ec)
+ {
+ warnif("size", file_path, ec, suppress_warning);
+ return 0;
+ }
+ return size;
+}
- if (utf8path.empty())
+// static
+std::filesystem::file_status LLFile::getStatus(const std::filesystem::path& file_path, bool dontFollowSymLink, int suppress_warning)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ std::error_code ec;
+ std::filesystem::file_status status;
+ if (dontFollowSymLink)
{
- char sep;
-#if LL_WINDOWS
- sep = '\\';
+ status = std::filesystem::symlink_status(file_path, ec);
+ }
+ else
+ {
+ status = std::filesystem::status(file_path, ec);
+ }
+ warnif("getStatus()", file_path, ec, suppress_warning);
+ return status;
+}
- std::vector<wchar_t> utf16path(MAX_PATH + 1);
- GetTempPathW(static_cast<DWORD>(utf16path.size()), &utf16path[0]);
- utf8path = ll_convert_wide_to_string(&utf16path[0]);
+// static
+const std::string& LLFile::tmpdir()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE;
+ static std::string temppath;
+ if (temppath.empty())
+ {
+#if LL_WINDOWS
+ temppath = ll_convert<std::string>(std::filesystem::temp_directory_path().native());
+ char sep = '\\';
#else
- sep = '/';
-
- utf8path = LLStringUtil::getenv("TMPDIR", "/tmp/");
+ temppath = std::filesystem::temp_directory_path().string();
+ char sep = '/';
#endif
- if (utf8path[utf8path.size() - 1] != sep)
+ if (temppath[temppath.size() - 1] != sep)
{
- utf8path += sep;
+ temppath += sep;
}
}
- return utf8path.c_str();
+
+ return temppath;
}
#if LL_WINDOWS
/************** input file stream ********************************/
-llifstream::llifstream() {}
+// explicit
+llifstream::llifstream(const char* _Filename, ios_base::openmode _Mode) :
+ std::ifstream(ll_convert<std::wstring>(_Filename).c_str(), _Mode | ios_base::in)
+{
+}
// explicit
llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode):
@@ -580,17 +1077,37 @@ llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode):
{
}
+// explicit
+llifstream::llifstream(const std::filesystem::path& _Filepath, ios_base::openmode _Mode) :
+ std::ifstream(_Filepath, _Mode | ios_base::in)
+{
+}
+
+void llifstream::open(const char* _Filename, ios_base::openmode _Mode)
+{
+ std::ifstream::open(ll_convert<std::wstring>(_Filename).c_str(),
+ _Mode | ios_base::in);
+}
+
void llifstream::open(const std::string& _Filename, ios_base::openmode _Mode)
{
std::ifstream::open(ll_convert<std::wstring>(_Filename).c_str(),
_Mode | ios_base::in);
}
+void llifstream::open(const std::filesystem::path& _Filepath, ios_base::openmode _Mode)
+{
+ std::ifstream::open(_Filepath,
+ _Mode | ios_base::in);
+}
/************** output file stream ********************************/
-
-llofstream::llofstream() {}
+// explicit
+llofstream::llofstream(const char* _Filename, ios_base::openmode _Mode) :
+ std::ofstream(ll_convert<std::wstring>(_Filename).c_str(), _Mode | ios_base::out)
+{
+}
// explicit
llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode):
@@ -599,36 +1116,27 @@ llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode):
{
}
-void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode)
+// explicit
+llofstream::llofstream(const std::filesystem::path& _Filepath, ios_base::openmode _Mode) :
+ std::ofstream(_Filepath, _Mode | ios_base::out)
{
- std::ofstream::open(ll_convert<std::wstring>( _Filename ).c_str(),
- _Mode | ios_base::out);
}
-/************** helper functions ********************************/
+void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
+{
+ std::ofstream::open(ll_convert<std::wstring>(_Filename).c_str(), _Mode | ios_base::out);
+}
-std::streamsize llifstream_size(llifstream& ifstr)
+void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode)
{
- if(!ifstr.is_open()) return 0;
- std::streampos pos_old = ifstr.tellg();
- ifstr.seekg(0, ios_base::beg);
- std::streampos pos_beg = ifstr.tellg();
- ifstr.seekg(0, ios_base::end);
- std::streampos pos_end = ifstr.tellg();
- ifstr.seekg(pos_old, ios_base::beg);
- return pos_end - pos_beg;
+ std::ofstream::open(ll_convert<std::wstring>( _Filename ).c_str(),
+ _Mode | ios_base::out);
}
-std::streamsize llofstream_size(llofstream& ofstr)
+void llofstream::open(const std::filesystem::path& _Filepath, ios_base::openmode _Mode)
{
- if(!ofstr.is_open()) return 0;
- std::streampos pos_old = ofstr.tellp();
- ofstr.seekp(0, ios_base::beg);
- std::streampos pos_beg = ofstr.tellp();
- ofstr.seekp(0, ios_base::end);
- std::streampos pos_end = ofstr.tellp();
- ofstr.seekp(pos_old, ios_base::beg);
- return pos_end - pos_beg;
+ std::ofstream::open(_Filepath,
+ _Mode | ios_base::out);
}
#endif // LL_WINDOWS
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 04a2946ac4..8de3f5c9b4 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -35,133 +35,712 @@
* Attempts to mostly mirror the POSIX style IO functions.
*/
-typedef FILE LLFILE;
+#include "stdtypes.h"
#include <fstream>
+#include <filesystem>
#include <sys/stat.h>
#if LL_WINDOWS
+#include <windows.h>
// The Windows version of stat function and stat data structure are called _stat64
// We use _stat64 here to support 64-bit st_size and time_t values
-typedef struct _stat64 llstat;
+typedef struct _stat64 llstat;
#else
-typedef struct stat llstat;
#include <sys/types.h>
+typedef struct stat llstat;
#endif
-#ifndef S_ISREG
-# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
-#endif
-
-#ifndef S_ISDIR
-# define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
-#endif
+typedef FILE LLFILE;
-// Windows C runtime library does not define this and does not support symlink detection in the
-// stat functions but we do in our getattr() function
-#ifndef S_IFLNK
-#define S_IFLNK 0xA000 /* symlink */
-#endif
+#include "fsyspath.h"
+#include "llstring.h" // safe char* -> std::string conversion
-#ifndef S_ISLNK
-#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
+#if LL_WINDOWS
+#define LLFILE_MODE(flags) L##flags
+#else
+#define LLFILE_MODE(flags) flags
#endif
-#include "llstring.h" // safe char* -> std::string conversion
-
-/// LLFile is a class of static functions operating on paths
+/// This class provides a selection of functions to operate on files through names and
+/// a class implementation to represent a file for reading and writing to it
/// All the functions with a path string input take UTF8 path/filenames
-class LL_COMMON_API LLFile
+///
+/// @nosubgrouping
+///
+class LLFile
{
public:
+ // ================================================================================
+ /// @name Constants
+ ///
+ ///@{
+ /** These can be passed to the omode parameter of LLFile::open() and its constructor
+
+ This is similar to the openmode flags for std:fstream but not exactly the same
+ std::fstream open() does not allow to open a file for writing without either
+ forcing the file to be truncated on open or all write operations being always
+ appended to the end of the file or failing to open when the file does not exist.
+ But to allow implementing the LLAPRFile::writeEx() functionality we need to be
+ able to write at a random position to the file without truncating it on open.
+
+ any other combinations than listed here are not allowed and will cause an error
+
+ bin in out trunc app noreplace File exists File doesn't exist
+ ----------------------------------------------------------------------------------
+ - + - - - - Open at begin Failure to open
+ + + - - - - " "
+ - - + - - - " Create new
+ + - + - - - " "
+ - + + - - - " "
+ + + + - - - " "
+ ----------------------------------------------------------------------------------
+ - - + + - - Destroy contents Create new
+ + - + + - - " "
+ - + + + - - " "
+ + + + + - - " "
+ ----------------------------------------------------------------------------------
+ - - + x - + Failure to open Create new
+ + - + x - + " "
+ - + + x - + " "
+ + + + x - + " "
+ ----------------------------------------------------------------------------------
+ - - + - + - Write to end Create new
+ + - + - + - " "
+ - + + - + - " "
+ + + + - + - " "
+ ----------------------------------------------------------------------------------
+ */
+ static const std::ios_base::openmode app = static_cast<std::ios_base::openmode>(1 << 1); // append to end
+ static const std::ios_base::openmode ate = static_cast<std::ios_base::openmode>(1 << 2); // initialize to end
+ static const std::ios_base::openmode binary = static_cast<std::ios_base::openmode>(1 << 3); // binary mode
+ static const std::ios_base::openmode in = static_cast<std::ios_base::openmode>(1 << 4); // for reading
+ static const std::ios_base::openmode out = static_cast<std::ios_base::openmode>(1 << 5); // for writing // for writing and reading
+ static const std::ios_base::openmode trunc = static_cast<std::ios_base::openmode>(1 << 6); // truncate on open
+ static const std::ios_base::openmode noreplace = static_cast<std::ios_base::openmode>(1 << 7); // no replace if it exists
+
+ /// Additional optional flags to omode in open() and lmode in fopen() or lock()
+ /// to indicate which sort of lock if any to attempt to get
+ ///
+ /// NOTE: there is a fundamental difference between platforms.
+ /// On Windows this lock is mandatory as it is part of the API to open a file handle and other
+ /// processes can not avoid it. If a file was opened denying other processes read and/or write
+ /// access, trying to open the same file in another process with that access will fail.
+ /// On Mac and Linux it is only an advisory lock implemented through the flock() system call.
+ /// This means that any other application needs to also attempt to at least acquire a shared
+ /// lock on the file in order to notice that the file is actually already locked. It can
+ /// therefore not be used to prevent random other applications from accessing the file, but it
+ /// works for other viewer processes when they use either the LLFile::open() or LLFile::fopen()
+ /// functions with the appropriate lock flags to open a file.
+ static const std::ios_base::openmode exclusive = static_cast<std::ios_base::openmode>(1 << 16);
+ static const std::ios_base::openmode shared = static_cast<std::ios_base::openmode>(1 << 17);
+
+ /// Additional lmode flag to indicate to rather fail instead of blocking when trying
+ /// to acquire a lock with LLFile::lock()
+ static const std::ios_base::openmode noblock = static_cast<std::ios_base::openmode>(1 << 18);
+
+ /// The mask value for the lock mask bits
+ static const std::ios_base::openmode lock_mask = static_cast<std::ios_base::openmode>(exclusive | shared);
+
+ /// One of these can be passed to the dir parameter of LLFile::seek()
+ static const std::ios_base::seekdir beg = std::ios_base::beg;
+ static const std::ios_base::seekdir cur = std::ios_base::cur;
+ static const std::ios_base::seekdir end = std::ios_base::end;
+ ///@}
+
+ // ================================================================================
+ /// @name constructor/deconstructor
+ ///
+ ///@{
+ /// default constructor
+ LLFile() : mHandle(InvalidHandle) {}
+
+ /// no copy constructor
+ LLFile(const LLFile&) = delete;
+
+ /// move constructor
+ LLFile(LLFile&& other) noexcept
+ {
+ mHandle = other.mHandle;
+ other.mHandle = InvalidHandle;
+ }
+
+ /// constructor opening the file
+ explicit LLFile(const char* filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) :
+ mHandle(InvalidHandle)
+ {
+ open(filename, omode, ec, perm);
+ }
+
+ explicit LLFile(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) :
+ mHandle(InvalidHandle)
+ {
+ open(filename, omode, ec, perm);
+ }
+
+ explicit LLFile(const std::filesystem::path& file_path, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666) :
+ mHandle(InvalidHandle)
+ {
+ open(file_path, omode, ec, perm);
+ }
+
+ /// destructor always attempts to close the file
+ ~LLFile() { close(); }
+ ///@}
+
+ // ================================================================================
+ /// @name operators
+ ///
+ ///@{
+ /// copy assignment deleted
+ LLFile& operator=(const LLFile&) = delete;
+
+ /// move assignment
+ LLFile& operator=(LLFile&& other) noexcept
+ {
+ close();
+ std::swap(mHandle, other.mHandle);
+ return *this;
+ }
+
+ // detect whether the wrapped file descriptor/handle is open or not
+ explicit operator bool() const { return (mHandle != InvalidHandle); }
+ bool operator!() { return (mHandle == InvalidHandle); }
+ ///@}
+
+ /// ================================================================================
+ /// @name class member methods
+ ///
+ /// These methods provide read and write support as well as additional functionality to query the size of
+ /// the file, change the position of the current file pointer or query it.
+ ///
+ /// Most of these functions take as one of their parameters a std::error_code object which can be used to
+ /// determine in more detail what error occurred if required
+ ///@{
+
+ /// Open a file with the specific open mode flags
+ inline int open(const char* filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return open(file_path, omode, ec, perm);
+ }
+ inline int open(const std::string& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return open(file_path, omode, ec, perm);
+ }
+ int open(const std::filesystem::path& filename, std::ios_base::openmode omode, std::error_code& ec, int perm = 0666);
+ ///< @returns 0 on success, -1 on failure
+
+ /// Determine the size of the opened file
+ S64 size(std::error_code& ec);
+ ///< @returns the number of bytes in the file or 0 on failure
+
+ /// Query the position of the current file pointer in the file
+ S64 tell(std::error_code& ec);
+ ///< @returns the absolute offset of the file pointer in bytes relative to the start of the file or -1 on failure
+
+ /// Move the file pointer to the specified absolute position relative to the start of the file
+ int seek(S64 pos, std::error_code& ec);
+ ///< @returns 0 on success, -1 on failure
+
+ /// Move the file pointer to the specified position relative to dir
+ int seek(S64 offset, std::ios_base::seekdir dir, std::error_code& ec);
+ ///< @returns 0 on success, -1 on failure
+
+ /// Read the specified number of bytes into the buffer starting at the current file pointer
+ S64 read(void* buffer, S64 nbytes, std::error_code& ec);
+ ///< If the file ends before the requested amount of bytes could be read, the function succeeds and
+ /// returns the bytes up to the end of the file. The return value indicates the number of actually
+ /// read bytes and can be therefore smaller than the requested amount.
+ /// @returns the number of bytes read from the file or -1 on failure
+
+ /// Write the specified number of bytes to the file starting at the current file pointer
+ S64 write(const void* buffer, S64 nbytes, std::error_code& ec);
+ ///< @returns the number of bytes written to the file or -1 on failure
+
+ /// Write into the file starting at the current file pointer using printf style format and
+ /// additional optional parameters as specified in the fmt string
+ S64 printf(const char* fmt, ...);
+ ///< @returns the number of bytes written to the file or -1 on failure
+
+ /// Attempt to acquire or release a lock on the file
+ int lock(int lmode, std::error_code& ec);
+ ///< lmode can be one of LLFile::exclusive or LLFile::shared to acquire the according lock
+ /// or 0 to give up an earlier acquired lock. Adding LLFile::noblock together with one of
+ /// the lock requests will cause the function to fail if the lock can not be acquired,
+ /// otherwise the function will block until the lock can be acquired.
+ /// @returns 0 on success, -1 on failure
+
+ /// close the file explicitly
+ int close(std::error_code& ec);
+ ///< @returns 0 on success, -1 on failure
+
+ /// Convenience function to close the file without additional parameters
+ int close();
+ ///< @returns 0 on success, -1 on failure
+ ///@}
+
+ /// ================================================================================
+ /// @name static member functions
+ ///
+ /// These functions are static and operate with UTF8 filenames as one of their parameters.
+ ///
+ ///@{
/// open a file with the specified access mode
- static LLFILE* fopen(const std::string& filename, const char* accessmode); /* Flawfinder: ignore */
+ ///
+#if LL_WINDOWS
+ using fopen_flags_t = wchar_t;
+#else
+ using fopen_flags_t = char;
+#endif
+ inline static LLFILE* fopen(const char* filename, const fopen_flags_t* accessmode, int lmode = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return LLFile::fopen(file_path, accessmode, lmode);
+ }
+ inline static LLFILE* fopen(const std::string& filename, const fopen_flags_t* accessmode, int lmode = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return LLFile::fopen(file_path, accessmode, lmode);
+ }
+ static LLFILE* fopen(const std::filesystem::path& file_path, const fopen_flags_t* accessmode, int lmode = 0);
///< 'accessmode' follows the rules of the Posix fopen() mode parameter
- /// "r" open the file for reading only and positions the stream at the beginning
- /// "r+" open the file for reading and writing and positions the stream at the beginning
- /// "w" open the file for reading and writing and truncate it to zero length
- /// "w+" open or create the file for reading and writing and truncate to zero length if it existed
- /// "a" open the file for reading and writing and position the stream at the end of the file
- /// "a+" open or create the file for reading and writing and position the stream at the end of the file
+ /// "r" open the file for reading only and positions the stream at the beginning
+ /// "r+" open the file for reading and writing and positions the stream at the beginning
+ /// "w" open the file for reading and writing and truncate it to zero length
+ /// "w+" open or create the file for reading and writing and truncate to zero length if it existed
+ /// "a" open the file for reading and writing and before every write position the stream at the end of the file
+ /// "a+" open or create the file for reading and writing and before every write position the stream at the end of the file
+ ///
+ /// in addition to these values, "b" can be appended to indicate binary stream access, but on Linux and Mac
+ /// this is strictly for compatibility and has no effect. On Windows this makes the file functions not
+ /// try to translate line endings. Windows also allows to append "t" to indicate text mode. If neither
+ /// "b" or "t" is defined, Windows uses the value set by _fmode which by default is _O_TEXT.
+ /// This means that it is always a good idea to append "b" specifically for binary file access to
+ /// avoid corruption of the binary consistency of the data stream when reading or writing
+ /// Other characters in 'accessmode', while possible on some platforms (Windows), will usually
+ /// cause an error on other platforms as fopen will verify this parameter
///
- /// in addition to these values, "b" can be appended to indicate binary stream access, but on Linux and Mac
- /// this is strictly for compatibility and has no effect. On Windows this makes the file functions not
- /// try to translate line endings. Windows also allows to append "t" to indicate text mode. If neither
- /// "b" or "t" is defined, Windows uses the value set by _fmode which by default is _O_TEXT.
- /// This means that it is always a good idea to append "b" specifically for binary file access to
- /// avoid corruption of the binary consistency of the data stream when reading or writing
- /// Other characters in 'accessmode' will usually cause an error as fopen will verify this parameter
- /// @returns a valid LLFILE* pointer on success or NULL on failure
+ /// lmode is optional and allows to lock the file for other processes either as a shared lock or an
+ /// exclusive lock. If the requested lock conflicts with an already existing lock, the open fails.
+ /// Pass either LLFIle::exclusive or LLFile::shared to this parameter if you want to prevent other
+ /// processes from reading (exclusive lock) or writing (shared lock) to the file. It will always use
+ /// LLFile::noblock, meaning the open will immediately fail if it conflicts with an existing lock on the
+ /// file.
+ ///
+ /// @returns a valid LLFILE* pointer on success that can be passed to the fread() and fwrite() functions
+ /// and some other f<something> functions in the Standard C library that accept a FILE* as parameter
+ /// or NULL on failure
+ /// Close a file handle opened with fopen() above
static int close(LLFILE * file);
-
- /// retrieve the content of a file into a string
- static std::string getContents(const std::string& filename);
- ///< @returns the content of the file or an empty string on failure
+ ///< @returns 0 on success and -1 on failure.
/// create a directory
- static int mkdir(const std::string& filename, int perms = 0700);
- ///< perms is a permissions mask like 0777 or 0700. In most cases it will be
- /// overridden by the user's umask. It is ignored on Windows.
- /// mkdir() considers "directory already exists" to be not an error.
- /// @returns 0 on success and -1 on failure.
-
- //// remove a directory
- static int rmdir(const std::string& filename, int suppress_error = 0);
- ///< pass ENOENT in the optional 'suppress_error' parameter
- /// if you don't want a warning in the log when the directory does not exist
+ inline static int mkdir(const char* dirname)
+ {
+ std::filesystem::path dir_path = fsyspath(dirname);
+ return mkdir(dir_path);
+ }
+ inline static int mkdir(const std::string& dirname)
+ {
+ std::filesystem::path dir_path = fsyspath(dirname);
+ return mkdir(dir_path);
+ }
+ static int mkdir(const std::filesystem::path& dirname);
+ ///< mkdir() considers "directory already exists" to be not an error.
/// @returns 0 on success and -1 on failure.
/// remove a file or directory
- static int remove(const std::string& filename, int suppress_error = 0);
- ///< pass ENOENT in the optional 'suppress_error' parameter
- /// if you don't want a warning in the log when the directory does not exist
+ inline static int remove(const char* filename, int suppress_warning = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return remove(file_path, suppress_warning);
+ }
+ inline static int remove(const std::string& filename, int suppress_warning = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return remove(file_path, suppress_warning);
+ }
+ static int remove(const std::filesystem::path& file_path, int suppress_warning = 0);
+ ///< pass an errno value (e.g., ENOENT) in the optional 'suppress_warning' parameter if you want to
+ /// suppress a warning in the log when the failure matches that errno (e.g., suppress warning if
+ /// the file or directory does not exist)
/// @returns 0 on success and -1 on failure.
/// rename a file
- static int rename(const std::string& filename, const std::string& newname, int suppress_error = 0);
+ inline static int rename(const char* filename, const char* newname, int suppress_warning = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ std::filesystem::path new_path = fsyspath(newname);
+ return rename(file_path, new_path, suppress_warning);
+ }
+ inline static int rename(const std::string& filename, const char* newname, int suppress_warning = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ std::filesystem::path new_path = fsyspath(newname);
+ return rename(file_path, new_path, suppress_warning);
+ }
+ inline static int rename(const char* filename, const std::string& newname, int suppress_warning = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ std::filesystem::path new_path = fsyspath(newname);
+ return rename(file_path, new_path, suppress_warning);
+ }
+ inline static int rename(const std::string& filename, const std::string& newname, int suppress_warning = 0)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ std::filesystem::path new_path = fsyspath(newname);
+ return rename(file_path, new_path, suppress_warning);
+ }
+ static int rename(const std::filesystem::path& file_path, const std::filesystem::path& new_path, int suppress_warning = 0);
///< it will silently overwrite newname if it exists without returning an error
/// Posix guarantees that if newname already exists, then there will be no moment
/// in which for other processes newname does not exist. There is no such guarantee
- /// under Windows at this time. It may do it in the same way but the used Windows API
- /// does not make such guarantees.
+ /// under Windows at this time. It may do it in the same way but the used Windows
+ /// APIs do not make such guarantees.
/// @returns 0 on success and -1 on failure.
+ /// copy the contents of the file from 'source' to 'target'
+ inline static bool copy(const char* source, const char* target)
+ {
+ std::error_code ec;
+ return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec);
+ }
+ inline static bool copy(const char* source, const std::string& target)
+ {
+ std::error_code ec;
+ return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec);
+ }
+ inline static bool copy(const std::string& source, const char* target)
+ {
+ std::error_code ec;
+ return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec);
+ }
+ inline static bool copy(const std::string& source, const std::string& target)
+ {
+ std::error_code ec;
+ return copy(source, target, std::filesystem::copy_options::overwrite_existing, ec);
+ }
+ inline static bool copy(const std::filesystem::path& source_path, const std::filesystem::path& target_path)
+ {
+ std::error_code ec;
+ return copy(source_path, target_path, std::filesystem::copy_options::overwrite_existing, ec);
+ }
+ ///< Copies the contents of the file 'source' to the file 'target', overwriting 'target' if it already
+ /// existed.
+ /// This is a convenience function that implements the previous behavior of silently overwriting an
+ /// already existing target file. Consider using the function below if you desire a different
+ /// behavior when the target file already exists
+ /// @returns true on success and false on failure.
+
+ /// copy the contents of the file from 'from' to 'to'
+ inline static bool copy(const char* source, const char* target, std::filesystem::copy_options options, std::error_code& ec)
+ {
+ std::filesystem::path source_path = fsyspath(source);
+ std::filesystem::path target_path = fsyspath(target);
+ return copy(source_path, target_path, options, ec);
+ }
+ inline static bool copy(const char* source, const std::string& target, std::filesystem::copy_options options, std::error_code& ec)
+ {
+ std::filesystem::path source_path = fsyspath(source);
+ std::filesystem::path target_path = fsyspath(target);
+ return copy(source_path, target_path, options, ec);
+ }
+ inline static bool copy(const std::string& source, const char* target, std::filesystem::copy_options options, std::error_code& ec)
+ {
+ std::filesystem::path source_path = fsyspath(source);
+ std::filesystem::path target_path = fsyspath(target);
+ return copy(source_path, target_path, options, ec);
+ }
+ inline static bool copy(const std::string& source, const std::string& target, std::filesystem::copy_options options, std::error_code& ec)
+ {
+ std::filesystem::path source_path = fsyspath(source);
+ std::filesystem::path target_path = fsyspath(target);
+ return copy(source_path, target_path, options, ec);
+ }
+ static bool copy(const std::filesystem::path& source_path, const std::filesystem::path& target_path, std::filesystem::copy_options options, std::error_code& ec);
+ ///< Copies the contents of the file 'source' to the file 'target'. The options parameter allows to
+ /// specify what should happen if the "target" file already exists:
+ /// std::filesystem::copy_options::none - return an error in ec and fail
+ /// std::filesystem::copy_options::skip_existing - skip the operation and do not overwrite file
+ /// std::filesystem::copy_options::overwrite_existing - overwrite the file
+ /// std::filesystem::copy_options::update_existing - overwrite the file only if it is older than the file being copied
+ /// @returns true on success and false on failure.
+
+ /// retrieve the content of a file into a string
+ inline static std::string getContents(const char* filename)
+ {
+ std::error_code ec;
+ return getContents(filename, ec);
+ }
+ inline static std::string getContents(const std::string& filename)
+ {
+ std::error_code ec;
+ return getContents(filename, ec);
+ }
+ inline static std::string getContents(const std::filesystem::path& file_path)
+ {
+ std::error_code ec;
+ return getContents(file_path, ec);
+ }
+ inline static std::string getContents(const char* filename, std::error_code& ec)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return getContents(file_path, ec);
+ }
+ inline static std::string getContents(const std::string& filename, std::error_code& ec)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return getContents(file_path, ec);
+ }
+ static std::string getContents(const std::filesystem::path& file_path, std::error_code& ec);
+ ///< @returns the entire content of the file as std::string or an empty string on failure
+
+ /// read nBytes from the file into the buffer, starting at offset in the file
+ inline static S64 read(const char* filename, void* buf, S64 offset, S64 nbytes)
+ {
+ std::error_code ec;
+ return read(filename, buf, offset, nbytes, ec);
+ }
+ inline static S64 read(const std::string& filename, void* buf, S64 offset, S64 nbytes)
+ {
+ std::error_code ec;
+ return read(filename, buf, offset, nbytes, ec);
+ }
+ inline static S64 read(const std::filesystem::path& file_path, void* buf, S64 offset, S64 nbytes)
+ {
+ std::error_code ec;
+ return read(file_path, buf, offset, nbytes, ec);
+ }
+ inline static S64 read(const char* filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return read(file_path, buf, offset, nbytes, ec);
+ }
+ inline static S64 read(const std::string& filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return read(file_path, buf, offset, nbytes, ec);
+ }
+ static S64 read(const std::filesystem::path& filename, void* buf, S64 offset, S64 nbytes, std::error_code& ec);
+ ///< @returns bytes read on success, or -1 on failure
- /// copy the contents of file from 'from' to 'to' filename
- static bool copy(const std::string& from, const std::string& to);
- ///< @returns true on success and false on failure.
+ /// write nBytes from the buffer into the file, starting at offset in the file
+ inline static S64 write(const std::string& filename, const void* buf, S64 offset, S64 nbytes)
+ {
+ std::error_code ec;
+ std::filesystem::path file_path = fsyspath(filename);
+ return write(file_path, buf, offset, nbytes, ec);
+ }
+ inline static S64 write(const std::filesystem::path& filename, const void* buf, S64 offset, S64 nbytes)
+ {
+ std::error_code ec;
+ std::filesystem::path file_path = fsyspath(filename);
+ return write(file_path, buf, offset, nbytes, ec);
+ }
+ inline static S64 write(const std::string& filename, const void* buf, S64 offset, S64 nbytes, std::error_code& ec)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return write(file_path, buf, offset, nbytes, ec);
+ }
+ static S64 write(const std::filesystem::path& filename, const void* buf, S64 offset, S64 nbytes, std::error_code& ec);
+ ///< If a negative offset is provided, the file is opened in append mode and the
+ /// write will be appended to the end of the file.
+ /// @returns bytes written on success, or -1 on failure
/// return the file stat structure for filename
- static int stat(const std::string& filename, llstat* file_status, int suppress_error = ENOENT);
+ inline static int stat(const char* filename, llstat* file_status, const char* operation = nullptr, int suppress_warning = ENOENT)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return stat(file_path, file_status, operation, suppress_warning);
+ }
+ inline static int stat(const std::string& filename, llstat* file_status, const char* operation = nullptr, int suppress_warning = ENOENT)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return stat(file_path, file_status, operation, suppress_warning);
+ }
+ static int stat(const std::filesystem::path& file_path, llstat* file_status, const char *operation = nullptr, int suppress_warning = ENOENT);
///< for compatibility with existing uses of LL_File::stat() we use ENOENT as default in the
- /// optional 'suppress_error' parameter to avoid spamming the log with warnings when the API
+ /// optional 'suppress_warning' parameter to avoid spamming the log with warnings when the API
/// is used to detect if a file exists
/// @returns 0 on success and -1 on failure.
- /// get the file or directory attributes for filename
- static unsigned short getattr(const std::string& filename, bool dontFollowSymLink = false, int suppress_error = ENOENT);
- ///< a more lightweight function on Windows to stat, that just returns the file attribute flags
- /// dontFollowSymLinks set to true returns the attributes of the symlink if it is one, rather than resolving it
- /// we pass by default ENOENT in the optional 'suppress_error' parameter to not spam the log with
- /// warnings when the file or directory does not exist
- /// @returns 0 on failure and a st_mode value with either S_IFDIR or S_IFREG set otherwise
- /// together with the three access bits which under Windows only the write bit is relevant.
+ /// get the std::filesystem::file_status for filename
+ inline static std::filesystem::file_status getStatus(const char* filename, bool dontFollowSymLink = false, int suppress_warning = ENOENT)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return getStatus(file_path, dontFollowSymLink, suppress_warning);
+ }
+ inline static std::filesystem::file_status getStatus(const std::string& filename, bool dontFollowSymLink = false, int suppress_warning = ENOENT)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return getStatus(file_path, dontFollowSymLink, suppress_warning);
+ }
+ static std::filesystem::file_status getStatus(const std::filesystem::path& file_path, bool dontFollowSymLink = false, int suppress_warning = ENOENT);
+ ///< dontFollowSymLinks set to true returns the std::filesystem::file_status of the symlink if it
+ /// is one, rather than resolving it. We pass by default ENOENT in the optional 'suppress_warning'
+ /// parameter to not spam the log with warnings when the file or directory does not exist
+ /// @returns a std::filesystem::file_status value that can be passed to the appropriate std::filesystem::exists()
+ /// and other APIs accepting a file_status.
+
+ /// get the size of a file in bytes
+ inline static S64 size(const char* filename, int suppress_warning = ENOENT)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return size(file_path, suppress_warning);
+ }
+ inline static S64 size(const std::string& filename, int suppress_warning = ENOENT)
+ {
+ std::filesystem::path file_path = fsyspath(filename);
+ return size(file_path, suppress_warning);
+ }
+ static S64 size(const std::filesystem::path& file_path, int suppress_warning = ENOENT);
+ ///< we pass by default ENOENT in the optional 'suppress_warning' parameter to not spam
+ /// the log with warnings when the file does not exist
+ /// @returns the file size on success or 0 on failure.
+
+ /// check if filename is an existing file or directory
+ inline static bool exists(const char* filename)
+ {
+ std::filesystem::file_status status = getStatus(filename);
+ return std::filesystem::exists(status);
+ }
+ inline static bool exists(const std::string& filename)
+ {
+ std::filesystem::file_status status = getStatus(filename);
+ return std::filesystem::exists(status);
+ }
+ inline static bool exists(const std::filesystem::path& file_path)
+ {
+ std::filesystem::file_status status = getStatus(file_path);
+ return std::filesystem::exists(status);
+ }
+ ///< @returns true if the path is for an existing file or directory
/// check if filename is an existing directory
- static bool isdir(const std::string& filename);
+ inline static bool isdir(const char* filename)
+ {
+ std::filesystem::file_status status = getStatus(filename);
+ return std::filesystem::is_directory(status);
+ }
+ inline static bool isdir(const std::string& filename)
+ {
+ std::filesystem::file_status status = getStatus(filename);
+ return std::filesystem::is_directory(status);
+ }
+ inline static bool isdir(const std::filesystem::path& file_path)
+ {
+ std::filesystem::file_status status = getStatus(file_path);
+ return std::filesystem::is_directory(status);
+ }
///< @returns true if the path is for an existing directory
/// check if filename is an existing file
- static bool isfile(const std::string& filename);
+ inline static bool isfile(const char* filename)
+ {
+ std::filesystem::file_status status = getStatus(filename);
+ return std::filesystem::is_regular_file(status);
+ }
+ inline static bool isfile(const std::string& filename)
+ {
+ std::filesystem::file_status status = getStatus(filename);
+ return std::filesystem::is_regular_file(status);
+ }
+ inline static bool isfile(const std::filesystem::path& file_path)
+ {
+ std::filesystem::file_status status = getStatus(file_path);
+ return std::filesystem::is_regular_file(status);
+ }
///< @returns true if the path is for an existing file
/// check if filename is a symlink
- static bool islink(const std::string& filename);
+ inline static bool islink(const char* filename)
+ {
+ std::filesystem::file_status status = getStatus(filename, true);
+ return std::filesystem::is_symlink(status);
+ }
+ inline static bool islink(const std::string& filename)
+ {
+ std::filesystem::file_status status = getStatus(filename, true);
+ return std::filesystem::is_symlink(status);
+ }
+ inline static bool islink(const std::filesystem::path& file_path)
+ {
+ std::filesystem::file_status status = getStatus(file_path, true);
+ return std::filesystem::is_symlink(status);
+ }
///< @returns true if the path is pointing at a symlink
/// return a path to the temporary directory on the system
- static const char * tmpdir();
+ static const std::string& tmpdir();
+
+private:
+#if LL_WINDOWS
+ typedef HANDLE llfile_handle_t;
+ const llfile_handle_t InvalidHandle = INVALID_HANDLE_VALUE;
+ llfile_handle_t mHandle = INVALID_HANDLE_VALUE; // The file handle/descriptor
+#else
+ typedef int llfile_handle_t;
+ const llfile_handle_t InvalidHandle = -1;
+ llfile_handle_t mHandle = -1; // The file handle/descriptor
+#endif
+
+ std::ios_base::openmode mOpen{}; // Used to emulate std::ios_base::app under Windows
+};
+
+#if LL_WINDOWS
+/**
+ * @brief Controlling input for files.
+ *
+ * This class supports reading from named files, using the inherited
+ * functions from std::ifstream. The only added value is that our constructor
+ * Does The Right Thing when passed a non-ASCII pathname. Sadly, that isn't
+ * true of Microsoft's std::ifstream.
+ */
+class llifstream : public std::ifstream
+{
+ // input stream associated with a C stream
+ public:
+ // Constructors:
+ /**
+ * @brief Default constructor.
+ *
+ * Initializes @c sb using its default constructor, and passes
+ * @c &sb to the base class initializer. Does not open any files
+ * (you haven't given it a filename to open).
+ */
+ llifstream() = default;
+
+ /**
+ * @brief Create an input file stream.
+ * @param Filename String specifying the filename.
+ * @param Mode Open file in specified mode (see std::ios_base).
+ *
+ * @c ios_base::in is automatically included in @a mode.
+ */
+ explicit llifstream(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::in);
+ explicit llifstream(const std::string& _Filename,
+ ios_base::openmode _Mode = ios_base::in);
+ explicit llifstream(const std::filesystem::path& _Filepath,
+ ios_base::openmode _Mode = ios_base::in);
+
+ /**
+ * @brief Opens an external file.
+ * @param Filename The name of the file.
+ * @param Node The open mode flags.
+ *
+ * Calls @c llstdio_filebuf::open(s,mode|in). If that function
+ * fails, @c failbit is set in the stream's error state.
+ */
+ void open(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::in);
+ void open(const std::string& _Filename,
+ ios_base::openmode _Mode = ios_base::in);
+ void open(const std::filesystem::path& _Filepath,
+ ios_base::openmode _Mode = ios_base::in);
};
/// RAII class
@@ -169,22 +748,19 @@ class LLUniqueFile
{
public:
// empty
- LLUniqueFile(): mFileHandle(nullptr) {}
+ LLUniqueFile() = default;
// wrap (e.g.) result of LLFile::fopen()
- LLUniqueFile(LLFILE* f): mFileHandle(f) {}
+ LLUniqueFile(LLFILE* f) : mFileHandle(f) {}
// no copy
LLUniqueFile(const LLUniqueFile&) = delete;
// move construction
LLUniqueFile(LLUniqueFile&& other) noexcept
{
- mFileHandle = other.mFileHandle;
+ mFileHandle = other.mFileHandle;
other.mFileHandle = nullptr;
}
// The point of LLUniqueFile is to close on destruction.
- ~LLUniqueFile()
- {
- close();
- }
+ ~LLUniqueFile() { close(); }
// simple assignment
LLUniqueFile& operator=(LLFILE* f)
@@ -209,7 +785,7 @@ public:
if (mFileHandle)
{
// in case close() throws, set mFileHandle null FIRST
- LLFILE* h{nullptr};
+ LLFILE* h{ nullptr };
std::swap(h, mFileHandle);
LLFile::close(h);
}
@@ -217,62 +793,16 @@ public:
// detect whether the wrapped LLFILE is open or not
explicit operator bool() const { return bool(mFileHandle); }
- bool operator!() { return ! mFileHandle; }
+ bool operator!() { return !mFileHandle; }
// LLUniqueFile should be usable for any operation that accepts LLFILE*
// (or FILE* for that matter)
operator LLFILE*() const { return mFileHandle; }
private:
- LLFILE* mFileHandle;
-};
-
-#if LL_WINDOWS
-/**
- * @brief Controlling input for files.
- *
- * This class supports reading from named files, using the inherited
- * functions from std::ifstream. The only added value is that our constructor
- * Does The Right Thing when passed a non-ASCII pathname. Sadly, that isn't
- * true of Microsoft's std::ifstream.
- */
-class LL_COMMON_API llifstream : public std::ifstream
-{
- // input stream associated with a C stream
- public:
- // Constructors:
- /**
- * @brief Default constructor.
- *
- * Initializes @c sb using its default constructor, and passes
- * @c &sb to the base class initializer. Does not open any files
- * (you haven't given it a filename to open).
- */
- llifstream();
-
- /**
- * @brief Create an input file stream.
- * @param Filename String specifying the filename.
- * @param Mode Open file in specified mode (see std::ios_base).
- *
- * @c ios_base::in is automatically included in @a mode.
- */
- explicit llifstream(const std::string& _Filename,
- ios_base::openmode _Mode = ios_base::in);
-
- /**
- * @brief Opens an external file.
- * @param Filename The name of the file.
- * @param Node The open mode flags.
- *
- * Calls @c llstdio_filebuf::open(s,mode|in). If that function
- * fails, @c failbit is set in the stream's error state.
- */
- void open(const std::string& _Filename,
- ios_base::openmode _Mode = ios_base::in);
+ LLFILE* mFileHandle = nullptr;
};
-
/**
* @brief Controlling output for files.
*
@@ -281,7 +811,7 @@ class LL_COMMON_API llifstream : public std::ifstream
* Right Thing when passed a non-ASCII pathname. Sadly, that isn't true of
* Microsoft's std::ofstream.
*/
-class LL_COMMON_API llofstream : public std::ofstream
+class llofstream : public std::ofstream
{
public:
// Constructors:
@@ -292,7 +822,7 @@ class LL_COMMON_API llofstream : public std::ofstream
* @c &sb to the base class initializer. Does not open any files
* (you haven't given it a filename to open).
*/
- llofstream();
+ llofstream() = default;
/**
* @brief Create an output file stream.
@@ -301,8 +831,12 @@ class LL_COMMON_API llofstream : public std::ofstream
*
* @c ios_base::out is automatically included in @a mode.
*/
+ explicit llofstream(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
explicit llofstream(const std::string& _Filename,
ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+ explicit llofstream(const std::filesystem::path& _Filepath,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
/**
* @brief Opens an external file.
@@ -311,21 +845,14 @@ class LL_COMMON_API llofstream : public std::ofstream
*
* @c ios_base::out is automatically included in @a mode.
*/
+ void open(const char* _Filename,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
void open(const std::string& _Filename,
ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
+ void open(const std::filesystem::path& _Filepath,
+ ios_base::openmode _Mode = ios_base::out|ios_base::trunc);
};
-
-/**
- * @brief filesize helpers.
- *
- * The file size helpers are not considered particularly efficient,
- * and should only be used for config files and the like -- not in a
- * loop.
- */
-std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr);
-std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr);
-
#else // ! LL_WINDOWS
// on non-windows, llifstream and llofstream are just mapped directly to the std:: equivalents
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/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 37d1c60f91..9d0ef45bee 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -837,7 +837,7 @@ private:
void get_proc_cpuinfo()
{
std::map< std::string, std::string > cpuinfo;
- LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
+ LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, LLFILE_MODE("rb"));
if(cpuinfo_fp)
{
char line[MAX_STRING];
@@ -954,7 +954,7 @@ private:
std::ostringstream s;
// *NOTE:Mani - This is for linux only.
- LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
+ LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, LLFILE_MODE("rb"));
if(cpuinfo)
{
char line[MAX_STRING];
diff --git a/indra/llcommon/llprofilercategories.h b/indra/llcommon/llprofilercategories.h
index 1c4f0f5624..261fdf14b7 100644
--- a/indra/llcommon/llprofilercategories.h
+++ b/indra/llcommon/llprofilercategories.h
@@ -48,6 +48,7 @@
#define LL_PROFILER_CATEGORY_ENABLE_DRAWPOOL 1
#define LL_PROFILER_CATEGORY_ENABLE_ENVIRONMENT 1
#define LL_PROFILER_CATEGORY_ENABLE_FACE 1
+//#define LL_PROFILER_CATEGORY_ENABLE_FILE 1
#define LL_PROFILER_CATEGORY_ENABLE_LLSD 1
#define LL_PROFILER_CATEGORY_ENABLE_LOGGING 1
#define LL_PROFILER_CATEGORY_ENABLE_MATERIAL 1
@@ -126,6 +127,14 @@
#define LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE
#endif
+#if LL_PROFILER_CATEGORY_ENABLE_FILE
+#define LL_PROFILE_ZONE_NAMED_CATEGORY_FILE LL_PROFILE_ZONE_NAMED
+#define LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE LL_PROFILE_ZONE_SCOPED
+#else
+#define LL_PROFILE_ZONE_NAMED_CATEGORY_FILE(name)
+#define LL_PROFILE_ZONE_SCOPED_CATEGORY_FILE
+#endif
+
#if LL_PROFILER_CATEGORY_ENABLE_LLSD
#define LL_PROFILE_ZONE_NAMED_CATEGORY_LLSD LL_PROFILE_ZONE_NAMED
#define LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD LL_PROFILE_ZONE_SCOPED
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 9b5dd2df39..5ef042b5a7 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -514,7 +514,7 @@ namespace {
#if LL_LINUX
constexpr U32 STATUS_SIZE = 2048;
- LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
+ LLFILE* status_filep = LLFile::fopen("/proc/self/status", LLFILE_MODE("rb"));
if (status_filep)
{
char buff[STATUS_SIZE]; /* Flawfinder: ignore */
@@ -1273,7 +1273,7 @@ bool gunzip_file(const std::string& srcfile, const std::string& dstfile)
src = gzopen(srcfile.c_str(), "rb");
#endif
if (! src) goto err;
- dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
+ dst = LLFile::fopen(tmpfile, LLFILE_MODE("wb")); /* Flawfinder: ignore */
if (! dst) goto err;
do
{
@@ -1314,7 +1314,7 @@ bool gzip_file(const std::string& srcfile, const std::string& dstfile)
#endif
if (! dst) goto err;
- src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
+ src = LLFile::fopen(srcfile, LLFILE_MODE("rb")); /* Flawfinder: ignore */
if (! src) goto err;
while ((bytes = (S32)fread(buffer, sizeof(U8), COMPRESS_BUFFER_SIZE, src)) > 0)
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 4aae90626e..867744a29d 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -151,6 +151,48 @@ U32 janky_fast_random_seeded_bytes(U32 seed, U32 val)
}
#endif
+void LLUUID::to_chars(char* out) const
+{
+ snprintf(out, UUID_STR_LENGTH, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (U8)(mData[0]),
+ (U8)(mData[1]),
+ (U8)(mData[2]),
+ (U8)(mData[3]),
+ (U8)(mData[4]),
+ (U8)(mData[5]),
+ (U8)(mData[6]),
+ (U8)(mData[7]),
+ (U8)(mData[8]),
+ (U8)(mData[9]),
+ (U8)(mData[10]),
+ (U8)(mData[11]),
+ (U8)(mData[12]),
+ (U8)(mData[13]),
+ (U8)(mData[14]),
+ (U8)(mData[15]));
+}
+
+void LLUUID::to_wchars(wchar_t* out) const
+{
+ swprintf(out, UUID_STR_LENGTH, L"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ (U8)(mData[0]),
+ (U8)(mData[1]),
+ (U8)(mData[2]),
+ (U8)(mData[3]),
+ (U8)(mData[4]),
+ (U8)(mData[5]),
+ (U8)(mData[6]),
+ (U8)(mData[7]),
+ (U8)(mData[8]),
+ (U8)(mData[9]),
+ (U8)(mData[10]),
+ (U8)(mData[11]),
+ (U8)(mData[12]),
+ (U8)(mData[13]),
+ (U8)(mData[14]),
+ (U8)(mData[15]));
+}
+
// Common to all UUID implementations
void LLUUID::toString(std::string& out) const
{
@@ -405,8 +447,8 @@ LLUUID LLUUID::combine(const LLUUID& other) const
std::ostream& operator<<(std::ostream& s, const LLUUID& uuid)
{
- std::string uuid_str;
- uuid.toString(uuid_str);
+ char uuid_str[UUID_STR_LENGTH];
+ uuid.to_chars(uuid_str);
s << uuid_str;
return s;
}
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index ca1cf03c4d..e6b0eea7a1 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -103,6 +103,8 @@ public:
friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
+ void to_chars(char* out) const;
+ void to_wchars(wchar_t* out) const;
void toString(std::string& out) const;
void toCompressedString(std::string& out) const;
diff --git a/indra/llcommon/tests/llfile_test.cpp b/indra/llcommon/tests/llfile_test.cpp
new file mode 100644
index 0000000000..ab4616cfb2
--- /dev/null
+++ b/indra/llcommon/tests/llfile_test.cpp
@@ -0,0 +1,299 @@
+/**
+ * @file llfile_test.cpp
+ * @author Frederick Martian
+ * @date 2025-11
+ * @brief LLFile test cases.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, 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 <tut/tut.hpp>
+#include "lltut.h"
+#include "linden_common.h"
+#include "llfile.h"
+
+namespace tut
+{
+ static void clear_entire_dir(const std::filesystem::path& dir_path)
+ {
+ std::error_code ec;
+ std::filesystem::remove_all(dir_path, ec);
+ }
+
+ static std::filesystem::path append_filename(const std::filesystem::path& dir, const std::u8string& element)
+ {
+ std::filesystem::path path = dir;
+ return path.append(element);
+ }
+
+ static std::filesystem::path get_testdir(const std::filesystem::path& tempdir)
+ {
+ return append_filename(tempdir, std::u8string(u8"test_dir"));
+ }
+
+ static std::filesystem::path get_testdir_unicode(const std::filesystem::path& tempdir)
+ {
+ // Example Unicode directory name: "test_ユニコード_dir"
+ return append_filename(tempdir, std::u8string(u8"test_\xE3\x83\xA6\xE3\x83\x8B\xE3\x82\xB3\xE3\x83\xBC\xE3\x83\x89_dir"));
+ }
+
+ struct llfile_test
+ {
+ std::filesystem::path tempdir = LLFile::tmpdir();
+ std::filesystem::path testdir = get_testdir(tempdir);
+ };
+ typedef test_group<llfile_test> llfile_test_t;
+ typedef llfile_test_t::object llfile_test_object_t;
+ tut::llfile_test_t tut_llfile_test("llfile_test");
+
+ template<> template<>
+ void llfile_test_object_t::test<1>()
+ {
+ // Test creating directories and files and deleting them and checking if the
+ // relevant status functions work as expected
+ ensure("LLFile::tmpdir() empty", !tempdir.empty());
+ ensure("LLFile::tmpdir() doesn't exist", LLFile::exists(tempdir));
+ ensure("LLFile::tmpdir() is not a directory", LLFile::isdir(tempdir));
+ ensure("LLFile::tmpdir() should not be a file", !LLFile::isfile(tempdir));
+
+ // Make sure there is nothing left from a previous test run
+ clear_entire_dir(testdir);
+ ensure("llfile_test should not exist anymore", !LLFile::exists(testdir));
+
+ int rc = LLFile::mkdir(testdir);
+ ensure("LLFile::mkdir() failed", rc == 0);
+ ensure("llfile_test should be a directory", LLFile::isdir(testdir));
+ rc = LLFile::mkdir(testdir);
+ ensure("LLFile::mkdir() should not fail when the directory already exists", rc == 0);
+
+ std::filesystem::path testfile1 = testdir;
+ testfile1.append("llfile_test.dat");
+ ensure("llfile_test1.dat should not yet exist", !LLFile::exists(testfile1));
+
+ const char* testdata = "testdata";
+ S64 bytes = LLFile::write(testfile1, testdata, 0, sizeof(testdata));
+ ensure("LLFile::write() did not write correctly", bytes == sizeof(testdata));
+
+ rc = LLFile::remove(testfile1);
+ ensure("LLFile::remove() for file test_file.dat", rc == 0);
+ ensure("llfile_test.dat should not exist anymore", !LLFile::exists(testfile1));
+ ensure("llfile_test.dat should not be a file", !LLFile::isfile(testfile1));
+ ensure("llfile_test.dat should not be a directory", !LLFile::isdir(testfile1));
+ ensure("llfile_test.dat should not be a symlink", !LLFile::islink(testfile1));
+
+ rc = LLFile::remove(testdir);
+ ensure("LLFile::remove() for directory llfile_test failed", rc == 0);
+ ensure("llfile_test should not exist anymore", !LLFile::exists(testdir));
+ }
+
+ template<> template<>
+ void llfile_test_object_t::test<2>()
+ {
+ // High level static file IO functions to read and write data files
+ LLFile::mkdir(testdir);
+ ensure("llfile_test should exist", LLFile::isdir(testdir));
+
+ std::filesystem::path testfile1 = testdir;
+ testfile1.append("llfile_test.dat");
+
+ std::string testdata1("testdata");
+ std::string testdata2("datateststuff");
+ std::time_t current = time(nullptr);
+ S64 bytes = LLFile::write(testfile1, testdata1.c_str(), 0, testdata1.length());
+ ensure("LLFile::write() did not write correctly", bytes == testdata1.length());
+ ensure("llfile_test.dat should exist", LLFile::exists(testfile1));
+ ensure("llfile_test.dat should be a file", LLFile::isfile(testfile1));
+ ensure("llfile_test.dat should not be a directory", !LLFile::isdir(testfile1));
+
+ bytes = LLFile::size(testfile1);
+ ensure("LLFile::size() did not return the correct size", bytes == testdata1.length());
+
+ std::string data = LLFile::getContents(testfile1);
+ ensure("LLFile::getContents() did not return the correct size data", data.length() == testdata1.length());
+ ensure_memory_matches("LLFile::getContents() did not read correct data", testdata1.c_str(), (U32)testdata1.length(), data.c_str(), (U32)data.length());
+
+ char buffer[1024];
+ bytes = LLFile::read(testfile1, buffer, 0, testdata1.length());
+ ensure("LLFile:read() did not return the correct size", bytes == testdata1.length());
+ ensure_memory_matches("LLFile::read() did not read correct data", testdata1.c_str(), (U32)bytes, buffer, (U32)bytes);
+
+ // What if we try to read more data than there is in the file?
+ bytes = LLFile::read(testfile1, buffer, 0, bytes + 10);
+ ensure("LLFile:read() did not correctly stop on eof", bytes == testdata1.length());
+ ensure_memory_matches("LLFile::read() did not read correct data", testdata1.c_str(), (U32)bytes, buffer, (U32)bytes);
+
+ // Let's append more data
+ bytes = LLFile::write(testfile1, testdata2.c_str(), -1, testdata2.length());
+ ensure("LLFile::write() did not write correctly", bytes == testdata2.length());
+
+ bytes = LLFile::size(testfile1);
+ ensure("LLFile::size() did not return the correct size", bytes == testdata1.length() + testdata2.length());
+ bytes = LLFile::read(testfile1, buffer, 0, bytes);
+ ensure("LLFile:read() did not read correct number of bytes", bytes == testdata1.length() + testdata2.length());
+ ensure_memory_matches("LLFile:read() did not read correct testdata1", testdata1.c_str(), (U32)testdata1.length(), buffer, (U32)testdata1.length());
+ ensure_memory_matches("LLFile:read() did not read correct testdata2", testdata2.c_str(), (U32)testdata2.length(), buffer + testdata1.length(), (U32)testdata2.length());
+ }
+
+ template<> template<>
+ void llfile_test_object_t::test<3>()
+ {
+ const size_t numints = 1024;
+
+ // Testing the LLFile class implementation
+ std::filesystem::path testfile = testdir;
+ testfile.append("llfile_test.bin");
+
+ int data[numints];
+ for (int &t : data)
+ {
+ t = rand();
+ }
+
+ std::error_code ec;
+ LLFile fileout(testfile, LLFile::out, ec);
+ ensure("LLFile constructor did not open correctly", (bool)fileout);
+ ensure("error_code from LLFile constructor should not indicate an error", !ec);
+ if (fileout)
+ {
+ S64 length = fileout.size(ec);
+ ensure("freshly created file should be empty", length == 0);
+ ensure("error_code from LLFile::size() should not indicate an error", !ec);
+ S64 bytes = fileout.write(data, sizeof(data), ec);
+ ensure("LLFile::write() did not write correctly", bytes == sizeof(data));
+ ensure("error_code from LLFile::write() should not indicate an error", !ec);
+ bytes = fileout.write(data, sizeof(data), ec);
+ ensure("LLFile::write() did not write correctly", bytes == sizeof(data));
+ ensure("error_code from LLFile::write() should not indicate an error", !ec);
+ bytes = fileout.size(ec);
+ ensure("LLFile::size() returned wrong size", bytes == 2 * sizeof(data));
+ ensure("error_code from LLFile::size() should not indicate an error", !ec);
+ fileout.close();
+ }
+
+ LLFile filein(testfile, LLFile::in, ec);
+ ensure("LLFile constructor did not open correctly", (bool)filein);
+ ensure("error_code from LLFile constructor should not indicate an error", !ec);
+ if (filein)
+ {
+ S64 length = filein.size(ec);
+ ensure("LLFile::size() returned wrong size", length == 2 * sizeof(data));
+ ensure("error_code from LLFile::size() should not indicate an error", !ec);
+ char* buffer = (char*)malloc(length);
+ S64 bytes = filein.read(buffer, length, ec);
+ ensure("LLFile::read() did not read correctly", bytes == length);
+ ensure("error_code from LLFile::read() should not indicate an error", !ec);
+ ensure_memory_matches("LLFile:read() did not read correct data1", data, (U32)sizeof(data), buffer, (U32)sizeof(data));
+ ensure_memory_matches("LLFile:read() did not read correct data2", data, (U32)sizeof(data), buffer + sizeof(data), (U32)sizeof(data));
+ S64 offset = filein.tell(ec);
+ ensure("LLFile::tell() returned a bad offset", offset == length);
+ ensure("error_code from LLFile::read() should not indicate an error", !ec);
+ offset = sizeof(data) / 2;
+ int rc = filein.seek(offset, ec);
+ ensure("LLFile::seek() indicated an error", rc == 0);
+ ensure("error_code from LLFile::seek() should not indicate an error", !ec);
+ bytes = filein.read(buffer, 2 * sizeof(data), ec);
+ ensure("LLFile::read() did not read correctly", bytes == sizeof(data) + offset);
+ ensure("error_code from LLFile::read() should not indicate an error", !ec);
+ ensure_memory_matches("LLFile:read() did not read correct data3", (char*)data + offset, (U32)offset, buffer, (U32)offset);
+ ensure_memory_matches("LLFile:read() did not read correct data4", (char*)data, (U32)sizeof(data), buffer + offset, (U32)sizeof(data));
+ filein.close();
+
+ free(buffer);
+ }
+ }
+
+ template<> template<>
+ void llfile_test_object_t::test<4>()
+ {
+ // Testing the LLFile class implementation with wrong paths and parameters
+ std::filesystem::path testfile = testdir;
+ testfile.append("llfile_test.bin");
+
+ std::error_code ec;
+ LLFile file(testfile, LLFile::out | LLFile::noreplace, ec);
+ ensure("LLFile constructor should not have opened the already existing file", !file);
+ ensure("error_code from LLFile constructor should indicate an error", (bool)ec);
+
+ LLFile::remove(testfile);
+ file = LLFile(testfile, LLFile::out | LLFile::app | LLFile::trunc, ec);
+ ensure("LLFile constructor should not have opened the file with conflicting flags", !file);
+ ensure("error_code from LLFile constructor should indicate an error", (bool)ec);
+
+ file = LLFile(testfile, LLFile::out | LLFile::app | LLFile::noreplace, ec);
+ ensure("LLFile constructor should not have opened the file with conflicting flags", !file);
+ ensure("error_code from LLFile constructor should indicate an error", (bool)ec);
+
+ testfile = testdir;
+ testfile.append("llfile_test");
+ testfile.append("llfile_test.bin");
+
+ file = LLFile(testfile, LLFile::in, ec);
+ ensure("LLFile constructor should not have been able to open the file in the non-existing directory", !file);
+ ensure("error_code from LLFile constructor should indicate an error", (bool)ec);
+ }
+
+ template<> template<>
+ void llfile_test_object_t::test<5>()
+ {
+ // Test file and directory operations with Unicode paths and filenames
+ std::filesystem::path testdir_unicode = get_testdir_unicode(tempdir);
+
+ // Unicode filename: "ファイル_テスト.bin" (means "file_test.bin" in Japanese)
+ std::string unicode_filename = "\xE3\x83\x95\xE3\x82\xA1\xE3\x82\xA4\xE3\x83\xAB_\xE3\x83\x86\xE3\x82\xB9\xE3\x83\x88.bin";
+ std::filesystem::path testfile_unicode = testdir_unicode;
+ testfile_unicode.append(unicode_filename);
+
+ // Clean up any previous test artifacts
+ clear_entire_dir(testdir_unicode);
+ ensure("Unicode test directory should not exist", !LLFile::exists(testdir_unicode));
+
+ // Create the Unicode directory
+ int rc = LLFile::mkdir(testdir_unicode);
+ ensure("LLFile::mkdir() failed for Unicode directory", rc == 0);
+ ensure("Unicode test directory should exist", LLFile::isdir(testdir_unicode));
+
+
+ ensure("Unicode test file should not exist", !LLFile::exists(testfile_unicode));
+
+ // Write to the Unicode file
+ const char* testdata = "unicode_testdata";
+ S64 bytes = LLFile::write(testfile_unicode, testdata, 0, strlen(testdata));
+ ensure("Unicode test file should exist", LLFile::exists(testfile_unicode));
+ ensure("Unicode test file should be a file", LLFile::isfile(testfile_unicode));
+ ensure("LLFile::write() did not write correctly to Unicode file", bytes == (S64)strlen(testdata));
+
+ // Read back the data
+ char buffer[64] = {};
+ bytes = LLFile::read(testfile_unicode, buffer, 0, sizeof(buffer));
+ ensure("LLFile::read() did not read correctly from Unicode file", bytes == (S64)strlen(testdata));
+ ensure_memory_matches("LLFile::read() did not read correct Unicode data", testdata, (U32)bytes, buffer, (U32)bytes);
+
+ // Remove the file and directory
+ rc = LLFile::remove(testfile_unicode);
+ ensure("LLFile::remove() failed for Unicode file", rc == 0);
+ ensure("Unicode test file should not exist after removal", !LLFile::exists(testfile_unicode));
+
+ rc = LLFile::remove(testdir_unicode);
+ ensure("LLFile::remove() failed for Unicode directory", rc == 0);
+ ensure("Unicode test directory should not exist after removal", !LLFile::exists(testdir_unicode));
+ }
+} // namespace tut
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index fa48bcdefd..ae20e7ed27 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -190,7 +190,7 @@ namespace tut
// computation, so I don't mind calling it twice.) Then take the
// basename.
reader_module(LLProcess::basename(
- reader.getName().substr(0, reader.getName().length()-3))),
+ reader.getPath().string().substr(0, reader.getPath().string().length()-3))),
PYTHON(LLStringUtil::getenv("PYTHON"))
{
ensure("Set PYTHON to interpreter pathname", !PYTHON.empty());
@@ -212,9 +212,9 @@ namespace tut
"time.sleep(1)\n");
LLLeapVector instances;
instances.push_back(LLLeap::create(get_test_name(),
- StringVec{PYTHON, script.getName()})->getWeak());
+ StringVec{PYTHON, script.getPath().string()})->getWeak());
instances.push_back(LLLeap::create(get_test_name(),
- StringVec{PYTHON, script.getName()})->getWeak());
+ StringVec{PYTHON, script.getPath().string()})->getWeak());
// In this case we're simply establishing that two LLLeap instances
// can coexist without throwing exceptions or bombing in any other
// way. Wait for them to terminate.
@@ -229,7 +229,7 @@ namespace tut
"import sys\n"
"sys.stderr.write('''Hello from Python!\n"
"note partial line''')\n");
- StringVec vcommand{ PYTHON, script.getName() };
+ StringVec vcommand{ PYTHON, script.getPath().string() };
CaptureLog log(LLError::LEVEL_INFO);
waitfor(LLLeap::create(get_test_name(), vcommand));
log.messageWith("Hello from Python!");
@@ -244,7 +244,7 @@ namespace tut
"print('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- StringVec{PYTHON, script.getName()}));
+ StringVec{PYTHON, script.getPath().string()}));
ensure_contains("error log line",
log.messageWith("invalid protocol"), "Hello from Python!");
}
@@ -259,7 +259,7 @@ namespace tut
"sys.stdout.write('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- StringVec{PYTHON, script.getName()}));
+ StringVec{PYTHON, script.getPath().string()}));
ensure_contains("error log line",
log.messageWith("Discarding"), "Hello from Python!");
}
@@ -273,7 +273,7 @@ namespace tut
"sys.stdout.write('5a2:something')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
- StringVec{PYTHON, script.getName()}));
+ StringVec{PYTHON, script.getPath().string()}));
ensure_contains("error log line",
log.messageWith("invalid protocol"), "5a2:");
}
@@ -386,7 +386,7 @@ namespace tut
" else 'bad: ' + str(resp)\n"
"send(pump='" << result.getName() << "', data=result)\n";});
waitfor(LLLeap::create(get_test_name(),
- StringVec{PYTHON, script.getName()}));
+ StringVec{PYTHON, script.getPath().string()}));
result.ensure();
}
@@ -445,7 +445,7 @@ namespace tut
" result = 'expected reqid=%s in %s' % (i, resp)\n"
" break\n"
"send(pump='" << result.getName() << "', data=result)\n";});
- waitfor(LLLeap::create(get_test_name(), StringVec{PYTHON, script.getName()}),
+ waitfor(LLLeap::create(get_test_name(), StringVec{PYTHON, script.getPath().string()}),
300); // needs more realtime than most tests
result.ensure();
}
@@ -512,7 +512,7 @@ namespace tut
" (start, large[start:end], echoed[start:end]))\n"
"sys.exit(1)\n";});
waitfor(LLLeap::create(test_name,
- StringVec{PYTHON, script.getName(), stringize(size)}),
+ StringVec{PYTHON, script.getPath().string(), stringize(size)}),
180); // try a longer timeout
result.ensure();
}
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index cdf9f70b6e..5e653d0ba0 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -87,12 +87,12 @@ static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR
* @param desc Optional description of the file for error message;
* defaults to "in <pathname>"
*/
-static std::string readfile(const std::string& pathname, const std::string& desc="")
+static std::string readfile(const std::filesystem::path& pathname, const std::string& desc="")
{
std::string use_desc(desc);
if (use_desc.empty())
{
- use_desc = "in " + pathname;
+ use_desc = "in " + pathname.string();
}
llifstream inf(pathname.c_str());
std::string output;
@@ -165,7 +165,7 @@ struct PythonProcessLauncher
mParams.desc = desc + " script";
mParams.executable = PYTHON;
- mParams.args.add(mScript.getName());
+ mParams.args.add(mScript.getPath().string());
}
/// Launch Python script; verify that it launched
@@ -233,11 +233,11 @@ struct PythonProcessLauncher
{
NamedTempFile out("out", ""); // placeholder
// pass name of this temporary file to the script
- mParams.args.add(out.getName());
+ mParams.args.add(out.getPath().string());
run();
// assuming the script wrote to that file, read it
std::string desc = "from " + mDesc + " script";
- return readfile(out.getName(), desc);
+ return readfile(out.getPath(), desc);
}
LLProcess::Params mParams;
@@ -271,23 +271,23 @@ public:
NamedTempDir():
mPath(NamedTempFile::temp_path()),
- mCreated(boost::filesystem::create_directories(mPath))
+ mCreated(std::filesystem::create_directories(mPath))
{
- mPath = boost::filesystem::canonical(mPath);
+ mPath = std::filesystem::canonical(mPath);
}
~NamedTempDir()
{
if (mCreated)
{
- boost::filesystem::remove_all(mPath);
+ std::filesystem::remove_all(mPath);
}
}
std::string getName() const { return mPath.string(); }
private:
- boost::filesystem::path mPath;
+ std::filesystem::path mPath;
bool mCreated;
};
@@ -440,7 +440,7 @@ namespace tut
#endif
// Have to have a named copy of this std::string so its c_str() value
// will persist.
- std::string scriptname(script.getName());
+ std::string scriptname(script.getPath().string());
argv.push_back(scriptname.c_str());
argv.push_back(NULL);
@@ -719,14 +719,14 @@ namespace tut
"with open(sys.argv[1], 'w') as f:\n"
" f.write('bad')\n");
NamedTempFile out("out", "not started");
- py.mParams.args.add(out.getName());
+ py.mParams.args.add(out.getPath().string());
py.launch();
// Wait for the script to wake up and do its first write
int i = 0, timeout = 60;
for ( ; i < timeout; ++i)
{
yield();
- if (readfile(out.getName(), "from kill() script") == "ok")
+ if (readfile(out.getPath(), "from kill() script") == "ok")
break;
}
// If we broke this loop because of the counter, something's wrong
@@ -745,7 +745,7 @@ namespace tut
// If kill() failed, the script would have woken up on its own and
// overwritten the file with 'bad'. But if kill() succeeded, it should
// not have had that chance.
- ensure_equals(get_test_name() + " script output", readfile(out.getName()), "ok");
+ ensure_equals(get_test_name() + " script output", readfile(out.getPath()), "ok");
}
template<> template<>
@@ -765,7 +765,7 @@ namespace tut
"# if caller hasn't managed to kill by now, bad\n"
"with open(sys.argv[1], 'w') as f:\n"
" f.write('bad')\n");
- py.mParams.args.add(out.getName());
+ py.mParams.args.add(out.getPath().string());
py.launch();
// Capture handle for later
phandle = py.mPy->getProcessHandle();
@@ -774,7 +774,7 @@ namespace tut
for ( ; i < timeout; ++i)
{
yield();
- if (readfile(out.getName(), "from kill() script") == "ok")
+ if (readfile(out.getPath(), "from kill() script") == "ok")
break;
}
// If we broke this loop because of the counter, something's wrong
@@ -787,7 +787,7 @@ namespace tut
// If kill() failed, the script would have woken up on its own and
// overwritten the file with 'bad'. But if kill() succeeded, it should
// not have had that chance.
- ensure_equals(get_test_name() + " script output", readfile(out.getName()), "ok");
+ ensure_equals(get_test_name() + " script output", readfile(out.getPath()), "ok");
}
template<> template<>
@@ -817,8 +817,8 @@ namespace tut
"# okay, saw 'go', write 'ack'\n"
"with open(sys.argv[1], 'w') as f:\n"
" f.write('ack')\n");
- py.mParams.args.add(from.getName());
- py.mParams.args.add(to.getName());
+ py.mParams.args.add(from.getPath().string());
+ py.mParams.args.add(to.getPath().string());
py.mParams.autokill = false;
py.launch();
// Capture handle for later
@@ -828,7 +828,7 @@ namespace tut
for ( ; i < timeout; ++i)
{
yield();
- if (readfile(from.getName(), "from autokill script") == "ok")
+ if (readfile(from.getPath(), "from autokill script") == "ok")
break;
}
// If we broke this loop because of the counter, something's wrong
@@ -840,14 +840,14 @@ namespace tut
// How do we know it's not terminated? By making it respond to
// a specific stimulus in a specific way.
{
- llofstream outf(to.getName().c_str());
+ llofstream outf(to.getPath());
outf << "go";
} // flush and close.
// now wait for the script to terminate... one way or another.
waitfor(phandle, "autokill script");
// If the LLProcess destructor implicitly called kill(), the
// script could not have written 'ack' as we expect.
- ensure_equals(get_test_name() + " script output", readfile(from.getName()), "ack");
+ ensure_equals(get_test_name() + " script output", readfile(from.getPath()), "ack");
}
template<> template<>
@@ -879,8 +879,8 @@ namespace tut
"# okay, saw 'go', write 'ack'\n"
"with open(sys.argv[1], 'w') as f:\n"
" f.write('ack')\n");
- py.mParams.args.add(from.getName());
- py.mParams.args.add(to.getName());
+ py.mParams.args.add(from.getPath().string());
+ py.mParams.args.add(to.getPath().string());
py.mParams.autokill = true;
py.mParams.attached = false;
py.launch();
@@ -891,7 +891,7 @@ namespace tut
for ( ; i < timeout; ++i)
{
yield();
- if (readfile(from.getName(), "from autokill script") == "ok")
+ if (readfile(from.getPath(), "from autokill script") == "ok")
break;
}
// If we broke this loop because of the counter, something's wrong
@@ -903,14 +903,14 @@ namespace tut
// How do we know it's not terminated? By making it respond to
// a specific stimulus in a specific way.
{
- llofstream outf(to.getName().c_str());
+ llofstream outf(to.getPath());
outf << "go";
} // flush and close.
// now wait for the script to terminate... one way or another.
waitfor(phandle, "autokill script");
// If the LLProcess destructor implicitly called kill(), the
// script could not have written 'ack' as we expect.
- ensure_equals(get_test_name() + " script output", readfile(from.getName()), "ack");
+ ensure_equals(get_test_name() + " script output", readfile(from.getPath()), "ack");
}
template<> template<>
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 272eb55521..a7abfda099 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1808,7 +1808,7 @@ namespace tut
#if LL_WINDOWS
std::string q("\"");
std::string qPYTHON(q + PYTHON + q);
- std::string qscript(q + scriptfile.getName() + q);
+ std::string qscript(q + scriptfile.getPath().string() + q);
int rc = (int)_spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(),
std::forward<ARGS>(args)..., NULL);
if (rc == -1)
@@ -1825,7 +1825,7 @@ namespace tut
#else // LL_DARWIN, LL_LINUX
LLProcess::Params params;
params.executable = PYTHON;
- params.args.add(scriptfile.getName());
+ params.args.add(scriptfile.getPath().string());
for (const std::string& arg : StringVec{ std::forward<ARGS>(args)... })
{
params.args.add(arg);
@@ -2002,8 +2002,8 @@ namespace tut
" yield frombytes\n"
<< pydata <<
// Don't forget raw-string syntax for Windows pathnames.
- "debug = open(r'" << debug.getName() << "', 'w')\n"
- "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n";});
+ "debug = open(r'" << debug.getPath().string() << "', 'w')\n"
+ "verify(parse_each(open(r'" << file.getPath().string() << "', 'rb')))\n";});
}
catch (const failure&)
{
@@ -2111,13 +2111,13 @@ namespace tut
"]\n"
// Don't forget raw-string syntax for Windows pathnames.
// N.B. Using 'print' implicitly adds newlines.
- "with open(r'" << file.getName() << "', 'wb') as f:\n"
+ "with open(r'" << (const char*)file.getPath().u8string().c_str() << "', 'wb') as f:\n"
" for item in DATA:\n"
" serialized = llsd." << pyformatter << "(item)\n"
" f.write(lenformat.pack(len(serialized)))\n"
" f.write(serialized)\n";});
- llifstream inf(file.getName().c_str());
+ llifstream inf(file.getPath());
LLSD item;
try
{
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index 7efaebd569..4db44ff2a6 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -276,12 +276,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/llcorehttp/httpcommon.cpp b/indra/llcorehttp/httpcommon.cpp
index 315ff15ebb..dabc61975d 100644
--- a/indra/llcorehttp/httpcommon.cpp
+++ b/indra/llcorehttp/httpcommon.cpp
@@ -36,10 +36,6 @@
namespace LLCore
{
-HttpStatus::type_enum_t EXT_CURL_EASY;
-HttpStatus::type_enum_t EXT_CURL_MULTI;
-HttpStatus::type_enum_t LLCORE;
-
HttpStatus::operator U32() const
{
// Effectively, concatenate mType (high) with mStatus (low).
diff --git a/indra/llcorehttp/httpcommon.h b/indra/llcorehttp/httpcommon.h
index 1c003a0966..001fd08f93 100644
--- a/indra/llcorehttp/httpcommon.h
+++ b/indra/llcorehttp/httpcommon.h
@@ -340,9 +340,9 @@ struct HttpStatus
return *this;
}
- static const type_enum_t EXT_CURL_EASY = 0; ///< mStatus is an error from a curl_easy_*() call
- static const type_enum_t EXT_CURL_MULTI = 1; ///< mStatus is an error from a curl_multi_*() call
- static const type_enum_t LLCORE = 2; ///< mStatus is an HE_* error code
+ static constexpr type_enum_t EXT_CURL_EASY = 0; ///< mStatus is an error from a curl_easy_*() call
+ static constexpr type_enum_t EXT_CURL_MULTI = 1; ///< mStatus is an error from a curl_multi_*() call
+ static constexpr type_enum_t LLCORE = 2; ///< mStatus is an HE_* error code
///< 100-999 directly represent HTTP status codes
/// Test for successful status in the code regardless
/// of error source (internal, libcurl).
diff --git a/indra/llcorehttp/llhttpconstants.cpp b/indra/llcorehttp/llhttpconstants.cpp
index 7a671543d9..7a671543d9 100755..100644
--- a/indra/llcorehttp/llhttpconstants.cpp
+++ b/indra/llcorehttp/llhttpconstants.cpp
diff --git a/indra/llcorehttp/llhttpconstants.h b/indra/llcorehttp/llhttpconstants.h
index d05d0f1af1..d05d0f1af1 100755..100644
--- a/indra/llcorehttp/llhttpconstants.h
+++ b/indra/llcorehttp/llhttpconstants.h
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index c7c50e6166..c7c50e6166 100755..100644
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index 190539cea5..1a647362c5 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -30,8 +30,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
-#else
-#include <direct.h>
#endif
#include "lldir.h"
@@ -43,7 +41,6 @@
#include "lldiriterator.h"
#include "stringize.h"
#include "llstring.h"
-#include <boost/filesystem.hpp>
#include <boost/bind.hpp>
#include <algorithm>
@@ -93,30 +90,20 @@ LLDir::~LLDir()
std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
{
- //Returns a vector of fullpath filenames.
-
-#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path p(ll_convert<std::wstring>(dirname));
-#else
- boost::filesystem::path p(dirname);
-#endif
-
+ // Returns a vector of filenames in the directory.
+ fsyspath dir_path(dirname);
std::vector<std::string> v;
-
- boost::system::error_code ec;
- if (exists(p, ec) && !ec.failed())
+ std::error_code ec;
+ if (std::filesystem::is_directory(dir_path, ec))
{
- if (is_directory(p, ec) && !ec.failed())
+ std::filesystem::directory_iterator end_iter;
+ for (std::filesystem::directory_iterator dir_itr(dir_path);
+ dir_itr != end_iter;
+ ++dir_itr)
{
- boost::filesystem::directory_iterator end_iter;
- for (boost::filesystem::directory_iterator dir_itr(p);
- dir_itr != end_iter;
- ++dir_itr)
+ if (std::filesystem::is_regular_file(dir_itr->status()))
{
- if (boost::filesystem::is_regular_file(dir_itr->status()))
- {
- v.push_back(dir_itr->path().filename().string());
- }
+ v.push_back(dir_itr->path().filename().string());
}
}
}
@@ -189,31 +176,31 @@ U32 LLDir::deleteDirAndContents(const std::string& dir_name)
try
{
-#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path dir_path(ll_convert<std::wstring>(dir_name));
-#else
- boost::filesystem::path dir_path(dir_name);
-#endif
-
- if (boost::filesystem::exists(dir_path))
+ fsyspath dir_path(dir_name);
+ if (std::filesystem::is_directory(dir_path))
{
- if (!boost::filesystem::is_empty(dir_path))
+ if (!std::filesystem::is_empty(dir_path))
{ // Directory has content
- num_deleted = (U32)boost::filesystem::remove_all(dir_path);
+ num_deleted = (U32)std::filesystem::remove_all(dir_path);
}
else
{ // Directory is empty
- boost::filesystem::remove(dir_path);
+ std::filesystem::remove(dir_path);
}
}
}
- catch (boost::filesystem::filesystem_error &er)
+ catch (std::filesystem::filesystem_error &er)
{
LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL;
}
return num_deleted;
}
+bool LLDir::fileExists(const std::string& filename) const
+{
+ return LLFile::exists(filename);
+}
+
const std::string LLDir::findFile(const std::string &filename,
const std::string& searchPath1,
const std::string& searchPath2,
@@ -1023,7 +1010,7 @@ bool LLDir::setCacheDir(const std::string &path)
{
LLFile::mkdir(path);
std::string tempname = add(path, "temp");
- LLFILE* file = LLFile::fopen(tempname,"wt");
+ LLFILE* file = LLFile::fopen(tempname, LLFILE_MODE("wt"));
if (file)
{
fclose(file);
@@ -1105,15 +1092,15 @@ void dir_exists_or_crash(const std::string &dir_name)
#if LL_WINDOWS
// *FIX: lame - it doesn't do the same thing on windows. not so
// important since we don't deploy simulator to windows boxes.
- LLFile::mkdir(dir_name, 0700);
+ LLFile::mkdir(dir_name);
#else
- struct stat dir_stat;
+ llstat dir_stat;
if(0 != LLFile::stat(dir_name, &dir_stat))
{
S32 stat_rv = errno;
if(ENOENT == stat_rv)
{
- if(0 != LLFile::mkdir(dir_name, 0700)) // octal
+ if(0 != LLFile::mkdir(dir_name))
{
LL_ERRS() << "Unable to create directory: " << dir_name << LL_ENDL;
}
diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h
index b0d2b6aada..8388816059 100644
--- a/indra/llfilesystem/lldir.h
+++ b/indra/llfilesystem/lldir.h
@@ -71,7 +71,7 @@ class LLDir
std::vector<std::string> getFilesInDir(const std::string &dirname);
// pure virtual functions
virtual std::string getCurPath() = 0;
- virtual bool fileExists(const std::string &filename) const = 0;
+ virtual bool fileExists(const std::string &filename) const;
const std::string findFile(const std::string& filename, const std::vector<std::string> filenames) const;
const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const;
diff --git a/indra/llfilesystem/lldir_linux.cpp b/indra/llfilesystem/lldir_linux.cpp
index b13b42c954..0ebaab1114 100644
--- a/indra/llfilesystem/lldir_linux.cpp
+++ b/indra/llfilesystem/lldir_linux.cpp
@@ -238,24 +238,6 @@ std::string LLDir_Linux::getCurPath()
return tmp_str;
}
-
-bool LLDir_Linux::fileExists(const std::string &filename) const
-{
- struct stat stat_data;
- // Check the age of the file
- // Now, we see if the files we've gathered are recent...
- int res = stat(filename.c_str(), &stat_data);
- if (!res)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
/*virtual*/ std::string LLDir_Linux::getLLPluginLauncher()
{
return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
diff --git a/indra/llfilesystem/lldir_linux.h b/indra/llfilesystem/lldir_linux.h
index bd031bd7bb..ad9cd76554 100644
--- a/indra/llfilesystem/lldir_linux.h
+++ b/indra/llfilesystem/lldir_linux.h
@@ -47,7 +47,6 @@ public:
virtual std::string getCurPath();
virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- /*virtual*/ bool fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp
index 2db1b6ec5d..b13e72ff15 100644
--- a/indra/llfilesystem/lldir_mac.cpp
+++ b/indra/llfilesystem/lldir_mac.cpp
@@ -35,7 +35,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <glob.h>
-#include <boost/filesystem.hpp>
+#include <filesystem>
#include "lldir_utils_objc.h"
// --------------------------------------------------------------------------------
@@ -45,15 +45,15 @@ static bool CreateDirectory(const std::string &parent,
std::string *fullname)
{
- boost::filesystem::path p(parent);
+ std::filesystem::path p(parent);
p /= child;
if (fullname)
*fullname = std::string(p.string());
- if (! boost::filesystem::create_directory(p))
+ if (! std::filesystem::create_directory(p))
{
- return (boost::filesystem::is_directory(p));
+ return (std::filesystem::is_directory(p));
}
return true;
}
@@ -75,10 +75,8 @@ LLDir_Mac::LLDir_Mac()
// mExecutablePathAndName
mExecutablePathAndName = executablepathstr;
- boost::filesystem::path executablepath(executablepathstr);
+ std::filesystem::path executablepath(executablepathstr);
-# ifndef BOOST_SYSTEM_NO_DEPRECATED
-#endif
mExecutableFilename = executablepath.filename().string();
mExecutableDir = executablepath.parent_path().string();
@@ -140,7 +138,7 @@ LLDir_Mac::LLDir_Mac()
mOSUserAppDir = mOSUserDir;
// mTempDir
- //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :(
+ //Aura 120920 std::filesystem::temp_directory_path() not yet implemented on mac. :(
std::string tmpdir = getSystemTempFolder();
if (!tmpdir.empty())
{
@@ -174,17 +172,9 @@ void LLDir_Mac::initAppDirs(const std::string &app_name,
std::string LLDir_Mac::getCurPath()
{
- return boost::filesystem::path( boost::filesystem::current_path() ).string();
+ return std::filesystem::path( std::filesystem::current_path() ).string();
}
-
-
-bool LLDir_Mac::fileExists(const std::string &filename) const
-{
- return boost::filesystem::exists(filename);
-}
-
-
/*virtual*/ std::string LLDir_Mac::getLLPluginLauncher()
{
return gDirUtilp->getAppRODataDir() + gDirUtilp->getDirDelimiter() +
diff --git a/indra/llfilesystem/lldir_mac.h b/indra/llfilesystem/lldir_mac.h
index f812ee810b..54dc2eb237 100644
--- a/indra/llfilesystem/lldir_mac.h
+++ b/indra/llfilesystem/lldir_mac.h
@@ -45,7 +45,6 @@ public:
const std::string& app_read_only_data_dir);
virtual std::string getCurPath();
- virtual bool fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
diff --git a/indra/llfilesystem/lldir_win32.cpp b/indra/llfilesystem/lldir_win32.cpp
index 9624b1197f..912a2963c6 100644
--- a/indra/llfilesystem/lldir_win32.cpp
+++ b/indra/llfilesystem/lldir_win32.cpp
@@ -373,24 +373,6 @@ std::string LLDir_Win32::getCurPath()
return ll_convert<std::string>(std::wstring(w_str));
}
-
-bool LLDir_Win32::fileExists(const std::string &filename) const
-{
- llstat stat_data;
- // Check the age of the file
- // Now, we see if the files we've gathered are recent...
- int res = LLFile::stat(filename, &stat_data);
- if (!res)
- {
- return true;
- }
- else
- {
- return false;
- }
-}
-
-
/*virtual*/ std::string LLDir_Win32::getLLPluginLauncher()
{
return gDirUtilp->getExecutableDir() + gDirUtilp->getDirDelimiter() +
diff --git a/indra/llfilesystem/lldir_win32.h b/indra/llfilesystem/lldir_win32.h
index 21a3f1213b..c3a41d3e33 100644
--- a/indra/llfilesystem/lldir_win32.h
+++ b/indra/llfilesystem/lldir_win32.h
@@ -44,7 +44,6 @@ public:
/*virtual*/ std::string getCurPath();
/*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask);
- /*virtual*/ bool fileExists(const std::string &filename) const;
/*virtual*/ std::string getLLPluginLauncher();
/*virtual*/ std::string getLLPluginFilename(std::string base_name);
diff --git a/indra/llfilesystem/lldiriterator.cpp b/indra/llfilesystem/lldiriterator.cpp
index 57d4912c94..60b55c7bf3 100644
--- a/indra/llfilesystem/lldiriterator.cpp
+++ b/indra/llfilesystem/lldiriterator.cpp
@@ -29,9 +29,9 @@
#include "lldiriterator.h"
#include "llregex.h"
-#include <boost/filesystem.hpp>
+#include <filesystem>
-namespace fs = boost::filesystem;
+namespace fs = std::filesystem;
static std::string glob_to_regex(const std::string& glob);
@@ -52,11 +52,7 @@ private:
LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
: mIsValid(false)
{
-#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- fs::path dir_path(ll_convert<std::wstring>(dirname));
-#else
- fs::path dir_path(dirname);
-#endif
+ fs::path dir_path = fsyspath(dirname);
bool is_dir = false;
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index c75df16b7d..e971e324a0 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -34,8 +34,8 @@
#include "llapp.h"
#include "llassettype.h"
#include "lldir.h"
-#include <boost/filesystem.hpp>
#include <chrono>
+#include <filesystem>
#include "lldiskcache.h"
@@ -67,7 +67,7 @@ LLDiskCache::LLDiskCache(const std::string& cache_dir,
// Interaction through the filesystem itself should be safe. Let’s say thread
// A is accessing the cache file for reading/writing and thread B is trimming
// the cache. Let’s also assume using llifstream to open a file and
-// boost::filesystem::remove are not atomic (which will be pretty much the
+// std::filesystem::remove are not atomic (which will be pretty much the
// case).
// Now, A is trying to open the file using llifstream ctor. It does some
@@ -83,7 +83,7 @@ LLDiskCache::LLDiskCache(const std::string& cache_dir,
// garbage.)
// Other situation: B is trimming the cache and A wants to read a file that is
-// about to get deleted. boost::filesystem::remove does whatever it is doing
+// about to get deleted. std::filesystem::remove does whatever it is doing
// before actually deleting the file. If A opens the file before the file is
// actually gone, the OS call from B to delete the file will fail since the OS
// will prevent this. B continues with the next file. If the file is already
@@ -96,38 +96,34 @@ void LLDiskCache::purge()
LL_INFOS() << "Total dir size before purge is " << dirFileSize(sCacheDir) << LL_ENDL;
}
- boost::system::error_code ec;
+ std::error_code ec;
auto start_time = std::chrono::high_resolution_clock::now();
- typedef std::pair<std::time_t, std::pair<uintmax_t, std::string>> file_info_t;
+ typedef std::pair<std::filesystem::file_time_type, std::pair<uintmax_t, std::string>> file_info_t;
std::vector<file_info_t> file_info;
-#if LL_WINDOWS
- std::wstring cache_path(ll_convert<std::wstring>(sCacheDir));
-#else
- std::string cache_path(sCacheDir);
-#endif
- if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())
+ std::filesystem::path cache_path = fsyspath(sCacheDir);
+ if (std::filesystem::is_directory(cache_path, ec) && !ec)
{
- boost::filesystem::directory_iterator iter(cache_path, ec);
- while (iter != boost::filesystem::directory_iterator() && !ec.failed())
+ std::filesystem::directory_iterator iter(cache_path, ec);
+ while (iter != std::filesystem::directory_iterator() && !ec)
{
if(!LLApp::isRunning())
{
return;
}
- if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())
+ if (std::filesystem::is_regular_file(*iter, ec) && !ec)
{
if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos)
{
- uintmax_t file_size = boost::filesystem::file_size(*iter, ec);
- if (ec.failed())
+ uintmax_t file_size = std::filesystem::file_size(*iter, ec);
+ if (ec)
{
continue;
}
const std::string file_path = (*iter).path().string();
- const std::time_t file_time = boost::filesystem::last_write_time(*iter, ec);
- if (ec.failed())
+ const std::filesystem::file_time_type file_time = std::filesystem::last_write_time(*iter, ec);
+ if (ec)
{
continue;
}
@@ -167,8 +163,8 @@ void LLDiskCache::purge()
}
if (should_remove)
{
- boost::filesystem::remove(entry.second.second, ec);
- if (ec.failed())
+ std::filesystem::remove(entry.second.second, ec);
+ if (ec)
{
LL_WARNS() << "Failed to delete cache file " << entry.second.second << ": " << ec.message() << LL_ENDL;
}
@@ -196,7 +192,7 @@ void LLDiskCache::purge()
std::ostringstream line;
line << action << " ";
- line << entry.first << " ";
+ line << S64(entry.first.time_since_epoch().count()) << " ";
line << entry.second.first << " ";
line << entry.second.second;
line << " (" << file_size_total << "/" << mMaxSizeBytes << ")";
@@ -210,7 +206,9 @@ void LLDiskCache::purge()
const std::string LLDiskCache::metaDataToFilepath(const LLUUID& id, LLAssetType::EType at)
{
- return llformat("%s%s%s_%s_0.asset", sCacheDir.c_str(), gDirUtilp->getDirDelimiter().c_str(), CACHE_FILENAME_PREFIX.c_str(), id.asString().c_str());
+ char uuid_str[UUID_STR_LENGTH]{};
+ id.to_chars(uuid_str);
+ return llformat("%s%s%s_%s_0.asset", sCacheDir.c_str(), gDirUtilp->getDirDelimiter().c_str(), CACHE_FILENAME_PREFIX.c_str(), uuid_str);
}
const std::string LLDiskCache::getCacheInfo()
@@ -236,23 +234,19 @@ void LLDiskCache::clearCache()
* the component files but it's called infrequently so it's
* likely just fine
*/
- boost::system::error_code ec;
-#if LL_WINDOWS
- std::wstring cache_path(ll_convert<std::wstring>(sCacheDir));
-#else
- std::string cache_path(sCacheDir);
-#endif
- if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())
+ std::error_code ec;
+ std::filesystem::path cache_path = fsyspath(sCacheDir);
+ if (std::filesystem::is_directory(cache_path, ec) && !ec)
{
- boost::filesystem::directory_iterator iter(cache_path, ec);
- while (iter != boost::filesystem::directory_iterator() && !ec.failed())
+ std::filesystem::directory_iterator iter(cache_path, ec);
+ while (iter != std::filesystem::directory_iterator() && !ec)
{
- if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())
+ if (std::filesystem::is_regular_file(*iter, ec) && !ec)
{
if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos)
{
- boost::filesystem::remove(*iter, ec);
- if (ec.failed())
+ std::filesystem::remove(*iter, ec);
+ if (ec)
{
LL_WARNS() << "Failed to delete cache file " << *iter << ": " << ec.message() << LL_ENDL;
}
@@ -269,24 +263,20 @@ void LLDiskCache::removeOldVFSFiles()
static const char CACHE_FORMAT[] = "inv.llsd";
static const char DB_FORMAT[] = "db2.x";
- boost::system::error_code ec;
-#if LL_WINDOWS
- std::wstring cache_path(ll_convert<std::wstring>(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "")));
-#else
- std::string cache_path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""));
-#endif
- if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())
+ std::error_code ec;
+ std::filesystem::path cache_path = fsyspath(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""));
+ if (std::filesystem::is_directory(cache_path, ec) && !ec)
{
- boost::filesystem::directory_iterator iter(cache_path, ec);
- while (iter != boost::filesystem::directory_iterator() && !ec.failed())
+ std::filesystem::directory_iterator iter(cache_path, ec);
+ while (iter != std::filesystem::directory_iterator() && !ec)
{
- if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())
+ if (std::filesystem::is_regular_file(*iter, ec) && !ec)
{
if (((*iter).path().string().find(CACHE_FORMAT) != std::string::npos) ||
((*iter).path().string().find(DB_FORMAT) != std::string::npos))
{
- boost::filesystem::remove(*iter, ec);
- if (ec.failed())
+ std::filesystem::remove(*iter, ec);
+ if (ec)
{
LL_WARNS() << "Failed to delete cache file " << *iter << ": " << ec.message() << LL_ENDL;
}
@@ -310,23 +300,19 @@ uintmax_t LLDiskCache::dirFileSize(const std::string& dir)
* so if performance is ever an issue, optimizing this or removing it altogether,
* is an easy win.
*/
- boost::system::error_code ec;
-#if LL_WINDOWS
- std::wstring dir_path(ll_convert<std::wstring>(dir));
-#else
- std::string dir_path(dir);
-#endif
- if (boost::filesystem::is_directory(dir_path, ec) && !ec.failed())
+ std::error_code ec;
+ std::filesystem::path dir_path = fsyspath(dir);
+ if (std::filesystem::is_directory(dir_path, ec) && !ec)
{
- boost::filesystem::directory_iterator iter(dir_path, ec);
- while (iter != boost::filesystem::directory_iterator() && !ec.failed())
+ std::filesystem::directory_iterator iter(dir_path, ec);
+ while (iter != std::filesystem::directory_iterator() && !ec)
{
- if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())
+ if (std::filesystem::is_regular_file(*iter, ec) && !ec)
{
if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos)
{
- uintmax_t file_size = boost::filesystem::file_size(*iter, ec);
- if (!ec.failed())
+ uintmax_t file_size = std::filesystem::file_size(*iter, ec);
+ if (!ec)
{
total_file_size += file_size;
}
diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index 541266af4f..388cbc280f 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -34,8 +34,6 @@
#include "llfasttimer.h"
#include "lldiskcache.h"
-#include "boost/filesystem.hpp"
-
constexpr S32 LLFileSystem::READ = 0x00000001;
constexpr S32 LLFileSystem::WRITE = 0x00000002;
constexpr S32 LLFileSystem::READ_WRITE = 0x00000003; // LLFileSystem::READ & LLFileSystem::WRITE
@@ -51,22 +49,21 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_
mBytesRead = 0;
mMode = mode;
+ // build the filepath
+ mPath = fsyspath(LLDiskCache::metaDataToFilepath(mFileID, mFileType));
+
// This block of code was originally called in the read() method but after comments here:
// https://bitbucket.org/lindenlab/viewer/commits/e28c1b46e9944f0215a13cab8ee7dded88d7fc90#comment-10537114
// we decided to follow Henri's suggestion and move the code to update the last access time here.
if (mode == LLFileSystem::READ)
{
- // build the filename (TODO: we do this in a few places - perhaps we should factor into a single function)
- const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType);
-
// update the last access time for the file if it exists - this is required
// even though we are reading and not writing because this is the
// way the cache works - it relies on a valid "last accessed time" for
// each file so it knows how to remove the oldest, unused files
- bool exists = gDirUtilp->fileExists(filename);
- if (exists)
+ if (LLFile::exists(mPath))
{
- updateFileAccessTime(filename);
+ updateFileAccessTime();
}
}
}
@@ -77,21 +74,17 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil
LL_PROFILE_ZONE_SCOPED;
const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);
- llifstream file(filename, std::ios::binary);
- if (file.is_open())
- {
- file.seekg(0, std::ios::end);
- return file.tellg() > 0;
- }
- return false;
+ // not only test for existence but for the file to be not empty
+ S64 size = LLFile::size(filename);
+ return size > 0;
}
// static
-bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error /*= 0*/)
+bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_warning /*= 0*/)
{
const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);
- LLFile::remove(filename.c_str(), suppress_error);
+ LLFile::remove(filename.c_str(), suppress_warning);
return true;
}
@@ -115,29 +108,11 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
return true;
}
-// static
-S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type)
-{
- const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);
-
- S32 file_size = 0;
- llifstream file(filename, std::ios::binary);
- if (file.is_open())
- {
- file.seekg(0, std::ios::end);
- file_size = (S32)file.tellg();
- }
-
- return file_size;
-}
-
bool LLFileSystem::read(U8* buffer, S32 bytes)
{
bool success = false;
- const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType);
-
- llifstream file(filename, std::ios::binary);
+ llifstream file(mPath, std::ios::binary);
if (file.is_open())
{
file.seekg(mPosition, std::ios::beg);
@@ -177,13 +152,11 @@ bool LLFileSystem::eof() const
bool LLFileSystem::write(const U8* buffer, S32 bytes)
{
- const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType);
-
bool success = false;
if (mMode == APPEND)
{
- llofstream ofs(filename, std::ios::app | std::ios::binary);
+ llofstream ofs(mPath, std::ios::app | std::ios::binary);
if (ofs)
{
ofs.write((const char*)buffer, bytes);
@@ -196,7 +169,7 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes)
else if (mMode == READ_WRITE)
{
// Don't truncate if file already exists
- llofstream ofs(filename, std::ios::in | std::ios::binary);
+ llofstream ofs(mPath, std::ios::in | std::ios::binary);
if (ofs)
{
ofs.seekp(mPosition, std::ios::beg);
@@ -207,7 +180,7 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes)
else
{
// File doesn't exist - open in write mode
- ofs.open(filename, std::ios::binary);
+ ofs.open(mPath, std::ios::binary);
if (ofs.is_open())
{
ofs.write((const char*)buffer, bytes);
@@ -218,7 +191,7 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes)
}
else
{
- llofstream ofs(filename, std::ios::binary);
+ llofstream ofs(mPath, std::ios::binary);
if (ofs)
{
ofs.write((const char*)buffer, bytes);
@@ -269,7 +242,7 @@ S32 LLFileSystem::tell() const
S32 LLFileSystem::getSize() const
{
- return LLFileSystem::getFileSize(mFileID, mFileType);
+ return narrow(LLFile::size(mPath));
}
S32 LLFileSystem::getMaxSize() const
@@ -284,17 +257,18 @@ bool LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_typ
mFileID = new_id;
mFileType = new_type;
+ mPath = fsyspath(LLDiskCache::metaDataToFilepath(mFileID, mFileType));
return true;
}
bool LLFileSystem::remove() const
{
- LLFileSystem::removeFile(mFileID, mFileType);
+ LLFile::remove(mPath);
return true;
}
-void LLFileSystem::updateFileAccessTime(const std::string& file_path)
+void LLFileSystem::updateFileAccessTime()
{
/**
* Threshold in time_t units that is used to decide if the last access time
@@ -305,52 +279,32 @@ void LLFileSystem::updateFileAccessTime(const std::string& file_path)
*
* Let's start with 1 hour in time_t units and see how that unfolds
*/
- constexpr std::time_t time_threshold = 1 * 60 * 60;
+ constexpr std::chrono::hours time_threshold(1);
// current time
- const std::time_t cur_time = std::time(nullptr);
-
- boost::system::error_code ec;
-#if LL_WINDOWS
- // file last write time
- const std::time_t last_write_time = boost::filesystem::last_write_time(ll_convert<std::wstring>(file_path), ec);
- if (ec.failed())
- {
- LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL;
- return;
- }
+ const std::filesystem::file_time_type cur_time = std::chrono::file_clock::now();
- // delta between cur time and last time the file was written
- const std::time_t delta_time = cur_time - last_write_time;
-
- // we only write the new value if the time in time_threshold has elapsed
- // before the last one
- if (delta_time > time_threshold)
- {
- boost::filesystem::last_write_time(ll_convert<std::wstring>(file_path), cur_time, ec);
- }
-#else
+ std::error_code ec;
// file last write time
- const std::time_t last_write_time = boost::filesystem::last_write_time(file_path, ec);
- if (ec.failed())
+ const std::filesystem::file_time_type last_write_time = std::filesystem::last_write_time(mPath, ec);
+ if (ec)
{
- LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL;
+ LL_WARNS() << "Failed to read last write time for cache file " << mPath << ": " << ec.message() << LL_ENDL;
return;
}
// delta between cur time and last time the file was written
- const std::time_t delta_time = cur_time - last_write_time;
+ const auto delta_time = cur_time - last_write_time;
// we only write the new value if the time in time_threshold has elapsed
// before the last one
if (delta_time > time_threshold)
{
- boost::filesystem::last_write_time(file_path, cur_time, ec);
+ std::filesystem::last_write_time(mPath, cur_time, ec);
}
-#endif
- if (ec.failed())
+ if (ec)
{
- LL_WARNS() << "Failed to update last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL;
+ LL_WARNS() << "Failed to update last write time for cache file " << mPath << ": " << ec.message() << LL_ENDL;
}
}
diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h
index 10649b6920..bc8b9216bd 100644
--- a/indra/llfilesystem/llfilesystem.h
+++ b/indra/llfilesystem/llfilesystem.h
@@ -33,6 +33,7 @@
#include "lluuid.h"
#include "llassettype.h"
#include "lldiskcache.h"
+#include <filesystem>
class LLFileSystem
{
@@ -58,13 +59,12 @@ class LLFileSystem
* file in the cache is read (not written) so that the last time the file was
* accessed is up to date (This is used in the mechanism for purging the cache)
*/
- void updateFileAccessTime(const std::string& file_path);
+ void updateFileAccessTime();
static bool getExists(const LLUUID& file_id, const LLAssetType::EType file_type);
- static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error = 0);
+ static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_warning = 0);
static bool renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type,
const LLUUID& new_file_id, const LLAssetType::EType new_file_type);
- static S32 getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type);
public:
static const S32 READ;
@@ -73,6 +73,7 @@ class LLFileSystem
static const S32 APPEND;
protected:
+ std::filesystem::path mPath;
LLAssetType::EType mFileType;
LLUUID mFileID;
S32 mPosition;
diff --git a/indra/llfilesystem/tests/lldir_test.cpp b/indra/llfilesystem/tests/lldir_test.cpp
index a2104d1ef9..412feb147b 100644
--- a/indra/llfilesystem/tests/lldir_test.cpp
+++ b/indra/llfilesystem/tests/lldir_test.cpp
@@ -405,7 +405,7 @@ namespace tut
std::string makeTestFile( const std::string& dir, const std::string& file )
{
std::string path = dir + file;
- LLFILE* handle = LLFile::fopen( path, "w" );
+ LLFILE* handle = LLFile::fopen(path, LLFILE_MODE("w"));
ensure("failed to open test file '"+path+"'", handle != NULL );
// Harbison & Steele, 4th ed., p. 366: "If an error occurs, fputs
// returns EOF; otherwise, it returns some other, nonnegative value."
@@ -557,8 +557,8 @@ namespace tut
LLFile::remove(dir1files[i]);
LLFile::remove(dir2files[i]);
}
- LLFile::rmdir(dir1);
- LLFile::rmdir(dir2);
+ LLFile::remove(dir1);
+ LLFile::remove(dir2);
}
template<> template<>
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index ca8a4199e8..bea33c04ed 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -2036,6 +2036,25 @@ file_extensions[] =
{ "dxt", IMG_CODEC_DXT },
{ "png", IMG_CODEC_PNG }
};
+
+static struct
+{
+ const wchar_t* exten;
+ EImageCodec codec;
+}
+wide_file_extensions[] =
+{
+ { L"bmp", IMG_CODEC_BMP },
+ { L"tga", IMG_CODEC_TGA },
+ { L"j2c", IMG_CODEC_J2C },
+ { L"jp2", IMG_CODEC_J2C },
+ { L"texture", IMG_CODEC_J2C },
+ { L"jpg", IMG_CODEC_JPEG },
+ { L"jpeg", IMG_CODEC_JPEG },
+ { L"mip", IMG_CODEC_DXT },
+ { L"dxt", IMG_CODEC_DXT },
+ { L"png", IMG_CODEC_PNG }
+};
#define NUM_FILE_EXTENSIONS LL_ARRAY_SIZE(file_extensions)
#if 0
static std::string find_file(std::string &name, S8 *codec)
@@ -2056,7 +2075,8 @@ static std::string find_file(std::string &name, S8 *codec)
return std::string("");
}
#endif
-EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
+
+EImageCodec LLImageBase::getCodecFromExtension(std::string_view exten)
{
if (!exten.empty())
{
@@ -2068,6 +2088,20 @@ EImageCodec LLImageBase::getCodecFromExtension(const std::string& exten)
}
return IMG_CODEC_INVALID;
}
+
+EImageCodec LLImageBase::getCodecFromExtension(std::wstring_view exten)
+{
+ if (!exten.empty())
+ {
+ for (int i = 0; i < (int)(NUM_FILE_EXTENSIONS); i++)
+ {
+ if (exten == wide_file_extensions[i].exten)
+ return wide_file_extensions[i].codec;
+ }
+ }
+ return IMG_CODEC_INVALID;
+}
+
#if 0
bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip_only)
{
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 6b14b68c78..8569c28528 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
@@ -158,7 +159,8 @@ public:
// <= 0 priority means that there's no need for more data.
static F32 calc_download_priority(F32 virtual_size, F32 visible_area, S32 bytes_sent);
- static EImageCodec getCodecFromExtension(const std::string& exten);
+ static EImageCodec getCodecFromExtension(std::string_view exten);
+ static EImageCodec getCodecFromExtension(std::wstring_view exten);
//static LLTrace::MemStatHandle sMemStat;
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index c896d60c85..2ae7760d4c 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -166,7 +166,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
{
sJpegErrorEncountered = false;
clean();
- FILE* fp = LLFile::fopen(mSrcFilename, "rb");
+ FILE* fp = LLFile::fopen(mSrcFilename, LLFILE_MODE("rb"));
if (!fp)
{
setLastError("Unable to open file for reading", mSrcFilename);
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index 25232b77aa..7b09553974 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -1191,7 +1191,7 @@ bool LLImageTGA::loadFile( const std::string& path )
return false;
}
- LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */
+ LLFILE* file = LLFile::fopen(path, LLFILE_MODE("rb")); /* Flawfinder: ignore */
if( !file )
{
LL_WARNS() << "Couldn't open file " << path << LL_ENDL;
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/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 10fd56a68e..a8f0554a71 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -467,7 +467,7 @@ bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetTyp
else
{
LL_WARNS("AssetStorage") << "Asset vfile " << uuid << ":" << type
- << " found in static cache with bad size " << file.getSize() << ", ignoring" << LL_ENDL;
+ << " found in static cache with bad size " << size << ", ignoring" << LL_ENDL;
}
}
return false;
@@ -1402,7 +1402,7 @@ void LLAssetStorage::legacyGetDataCallback(const LLUUID &uuid,
uuid.toString(uuid_str);
filename = llformat("%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type));
- LLFILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("wb")); /* Flawfinder: ignore */
if (fp)
{
const S32 buf_size = 65536;
diff --git a/indra/llmessage/lltransfersourcefile.cpp b/indra/llmessage/lltransfersourcefile.cpp
index 77a6c466c7..d2d264c520 100644
--- a/indra/llmessage/lltransfersourcefile.cpp
+++ b/indra/llmessage/lltransfersourcefile.cpp
@@ -62,7 +62,7 @@ void LLTransferSourceFile::initTransfer()
return;
}
// Look for the file.
- mFP = LLFile::fopen(mParams.getFilename(), "rb"); /* Flawfinder: ignore */
+ mFP = LLFile::fopen(mParams.getFilename(), LLFILE_MODE("rb")); /* Flawfinder: ignore */
if (!mFP)
{
sendTransferStatus(LLTS_ERROR);
diff --git a/indra/llmessage/lltransfertargetfile.cpp b/indra/llmessage/lltransfertargetfile.cpp
index 6d8b69fa6f..05dba219ed 100644
--- a/indra/llmessage/lltransfertargetfile.cpp
+++ b/indra/llmessage/lltransfertargetfile.cpp
@@ -75,7 +75,7 @@ LLTSCode LLTransferTargetFile::dataCallback(const S32 packet_id, U8 *in_datap, c
if (!mFP)
{
- mFP = LLFile::fopen(mParams.mFilename, "wb"); /* Flawfinder: ignore */
+ mFP = LLFile::fopen(mParams.mFilename, LLFILE_MODE("wb")); /* Flawfinder: ignore */
if (!mFP)
{
diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp
index 71b910297b..5f27cc4827 100644
--- a/indra/llmessage/llxfer_file.cpp
+++ b/indra/llmessage/llxfer_file.cpp
@@ -161,7 +161,7 @@ S32 LLXfer_File::initializeRequest(U64 xfer_id,
S32 LLXfer_File::startDownload()
{
S32 retval = 0; // presume success
- mFp = LLFile::fopen(mTempFilename,"w+b"); /* Flawfinder : ignore */
+ mFp = LLFile::fopen(mTempFilename,LLFILE_MODE("w+b")); /* Flawfinder : ignore */
if (mFp)
{
fclose(mFp);
@@ -209,7 +209,7 @@ S32 LLXfer_File::startSend (U64 xfer_id, const LLHost &remote_host)
mBufferStartOffset = 0;
// We leave the file open, assuming we'll start reading and sending soon
- mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
+ mFp = LLFile::fopen(mLocalFilename, LLFILE_MODE("rb")); /* Flawfinder : ignore */
if (mFp)
{
fseek(mFp,0,SEEK_END);
@@ -252,7 +252,7 @@ S32 LLXfer_File::reopenFileHandle()
if (mFp == NULL)
{
- mFp = LLFile::fopen(mLocalFilename,"rb"); /* Flawfinder : ignore */
+ mFp = LLFile::fopen(mLocalFilename, LLFILE_MODE("rb")); /* Flawfinder : ignore */
if (mFp == NULL)
{
LL_INFOS("Xfer") << "Warning: " << mLocalFilename << " not found when re-opening file" << LL_ENDL;
@@ -313,7 +313,7 @@ S32 LLXfer_File::flush()
{
LL_ERRS("Xfer") << "Overwriting open file pointer!" << LL_ENDL;
}
- mFp = LLFile::fopen(mTempFilename,"a+b"); /* Flawfinder : ignore */
+ mFp = LLFile::fopen(mTempFilename, LLFILE_MODE("a+b")); /* Flawfinder : ignore */
if (mFp)
{
@@ -381,11 +381,11 @@ S32 LLXfer_File::processEOF()
}
else
{
- //LLFILE* fp = LLFile::fopen(mTempFilename, "r");
+ //LLFILE* fp = LLFile::fopen(mTempFilename, LLFILE_MODE("r"));
//LL_WARNS() << "File " << mTempFilename << " does "
// << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
//if(fp) fclose(fp);
- //fp = LLFile::fopen(mLocalFilename, "r");
+ //fp = LLFile::fopen(mLocalFilename, LLFILE_MODE("r"));
//LL_WARNS() << "File " << mLocalFilename << " does "
// << (!fp ? "not" : "" ) << " exit." << LL_ENDL;
//if(fp) fclose(fp);
@@ -452,8 +452,8 @@ U32 LLXfer_File::getXferTypeTag()
S32 copy_file(const std::string& from, const std::string& to)
{
S32 rv = 0;
- LLFILE* in = LLFile::fopen(from, "rb"); /*Flawfinder: ignore*/
- LLFILE* out = LLFile::fopen(to, "wb"); /*Flawfinder: ignore*/
+ LLFILE* in = LLFile::fopen(from, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
+ LLFILE* out = LLFile::fopen(to, LLFILE_MODE("wb")); /*Flawfinder: ignore*/
if(in && out)
{
S32 read = 0;
diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp
index e2937490ba..df58c8a7f3 100644
--- a/indra/llmessage/message.cpp
+++ b/indra/llmessage/message.cpp
@@ -2376,7 +2376,7 @@ void dump_prehash_files()
{
U32 i;
std::string filename("../../indra/llmessage/message_prehash.h");
- LLFILE* fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("w")); /* Flawfinder: ignore */
if (fp)
{
fprintf(
@@ -2407,7 +2407,7 @@ void dump_prehash_files()
fclose(fp);
}
filename = std::string("../../indra/llmessage/message_prehash.cpp");
- fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */
+ fp = LLFile::fopen(filename, LLFILE_MODE("w")); /* Flawfinder: ignore */
if (fp)
{
fprintf(
diff --git a/indra/llmessage/tests/lldatapacker_test.cpp b/indra/llmessage/tests/lldatapacker_test.cpp
index 746817936d..5823980d43 100644
--- a/indra/llmessage/tests/lldatapacker_test.cpp
+++ b/indra/llmessage/tests/lldatapacker_test.cpp
@@ -348,7 +348,7 @@ namespace tut
{
F32 f_val = 44.44f, f_unpkval;
- LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, "w+");
+ LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, LLFILE_MODE("w+"));
if(!fp)
{
LL_ERRS() << "File couldnt be open" << LL_ENDL;
@@ -403,7 +403,7 @@ namespace tut
LLVector4 unpkllvec4;
LLUUID unpkuuid;
- LLFILE* fp = LLFile::fopen(TEST_FILE_NAME,"w+");
+ LLFILE* fp = LLFile::fopen(TEST_FILE_NAME, LLFILE_MODE("w+"));
if(!fp)
{
LL_ERRS() << "File couldnt be open" << LL_ENDL;
diff --git a/indra/llmessage/tests/llmessageconfig_test.cpp b/indra/llmessage/tests/llmessageconfig_test.cpp
index 93443467a2..b8942e99b3 100644
--- a/indra/llmessage/tests/llmessageconfig_test.cpp
+++ b/indra/llmessage/tests/llmessageconfig_test.cpp
@@ -62,7 +62,7 @@ namespace tut
int rmfile = LLFile::remove((mTestConfigDir + "/message.xml"));
ensure_equals("rmfile value", rmfile, 0);
// rm temp dir
- int rmdir = LLFile::rmdir(mTestConfigDir);
+ int rmdir = LLFile::remove(mTestConfigDir);
ensure_equals("rmdir value", rmdir, 0);
}
diff --git a/indra/llmessage/tests/message_test.cpp b/indra/llmessage/tests/message_test.cpp
index 11cd710ef6..6fb2b92803 100644
--- a/indra/llmessage/tests/message_test.cpp
+++ b/indra/llmessage/tests/message_test.cpp
@@ -113,7 +113,7 @@ namespace tut
ensure_equals("rmfile value", rmfile, 0);
// rm temp dir
- int rmdir = LLFile::rmdir(mTestConfigDir);
+ int rmdir = LLFile::remove(mTestConfigDir);
ensure_equals("rmdir value", rmdir, 0);
}
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 ab88e4868e..e26c53bc2e 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1698,25 +1698,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)
{
@@ -1737,7 +1776,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)
{
@@ -1761,7 +1800,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 9c17cf3470..51301c7cac 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -449,9 +449,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/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 1da71e6bf4..f6738364a6 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -501,7 +501,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
open_file_name = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/errorF.glsl");
}
- file = LLFile::fopen(open_file_name, "r");
+ file = LLFile::fopen(open_file_name, LLFILE_MODE("r"));
}
else
#endif
@@ -529,7 +529,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
*/
LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL;
- file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */
+ file = LLFile::fopen(open_file_name, LLFILE_MODE("r")); /* Flawfinder: ignore */
if (file)
{
LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL;
@@ -1014,7 +1014,6 @@ void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version,
mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
LLFile::mkdir(mShaderCacheDir);
-
{
std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
if (gDirUtilp->fileExists(meta_out_path))
@@ -1077,7 +1076,7 @@ void LLShaderMgr::persistShaderCacheMetadata()
// Settings and shader cache get saved at different time, thus making
// RenderShaderCacheVersion unreliable when running multiple viewer
// instances, or for cases where viewer crashes before saving settings.
- // Dupplicate version to the cache itself.
+ // Duplicate version to the cache itself.
out["version"] = mShaderCacheVersion;
out["shaders"] = LLSD::emptyMap();
LLSD &shaders = out["shaders"];
@@ -1130,11 +1129,11 @@ bool LLShaderMgr::loadCachedProgramBinary(LLGLSLShader* shader)
{
std::vector<U8> in_data;
in_data.resize(shader_info.mBinaryLength);
-
- LLUniqueFile filep = LLFile::fopen(in_path, "rb");
- if (filep)
+ std::error_code ec;
+ LLFile filep = LLFile(in_path, LLFile::in | LLFile::binary, ec);
+ if (!ec && (bool)filep)
{
- size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep);
+ size_t result = filep.read(in_data.data(), in_data.size(), ec);
filep.close();
if (result == in_data.size())
@@ -1179,11 +1178,12 @@ bool LLShaderMgr::saveCachedProgramBinary(LLGLSLShader* shader)
if (error == GL_NO_ERROR)
{
std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
- LLUniqueFile outfile = LLFile::fopen(out_path, "wb");
- if (outfile)
+ std::error_code ec;
+ LLFile filep = LLFile(out_path, LLFile::out | LLFile::binary, ec);
+ if (filep)
{
- fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile);
- outfile.close();
+ filep.write(program_binary.data(), program_binary.size(), ec);
+ filep.close();
binary_info.mLastUsedTime = (F32)LLTimer::getTotalSeconds();
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index b534c8d4e8..ef62666918 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/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 1829479ace..662fe97689 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -3198,6 +3198,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/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
index a792cb8103..cd062b23b8 100644
--- a/indra/llui/lluicolortable.cpp
+++ b/indra/llui/lluicolortable.cpp
@@ -298,7 +298,7 @@ void LLUIColorTable::saveUserSettings() const
if(!output_node->isNull())
{
const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml");
- LLFILE *fp = LLFile::fopen(filename, "w");
+ LLFILE *fp = LLFile::fopen(filename, LLFILE_MODE("w"));
if(fp != NULL)
{
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index 8fd85a89a1..9bf2f4220c 100644
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -637,7 +637,7 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p
}
}
- LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), "w");
+ LLFILE* xsd_file = LLFile::fopen(file_name.c_str(), LLFILE_MODE("w"));
LLXMLNode::writeHeaderToFile(xsd_file);
root_nodep->writeToFile(xsd_file);
fclose(xsd_file);
@@ -1326,7 +1326,7 @@ void LLXUIParser::parserError(const std::string& message)
struct ScopedFile
{
- ScopedFile( const std::string& filename, const char* accessmode )
+ ScopedFile( const std::string& filename, const LLFile::fopen_flags_t* accessmode )
{
mFile = LLFile::fopen(filename, accessmode);
}
@@ -1397,7 +1397,7 @@ bool LLSimpleXUIParser::readXUI(const std::string& filename, LLInitParam::BaseBl
mCurReadDepth = 0;
setParseSilently(silent);
- ScopedFile file(filename, "rb");
+ ScopedFile file(filename, LLFILE_MODE("rb"));
if( !file.isOpen() )
{
LL_WARNS("ReadXUI") << "Unable to open file " << filename << LL_ENDL;
diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp
index 8277c23691..8277c23691 100755..100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
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/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index 562a30e8d1..8a95ab2cc2 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
@@ -399,7 +402,7 @@ void LLControlGroup::cleanup()
if(mSettingsProfile && getCount.size() != 0)
{
std::string file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, SETTINGS_PROFILE);
- LLFILE* out = LLFile::fopen(file, "w"); /* Flawfinder: ignore */
+ LLFILE* out = LLFile::fopen(file, LLFILE_MODE("w")); /* Flawfinder: ignore */
if(!out)
{
LL_WARNS("SettingsProfile") << "Error opening " << SETTINGS_PROFILE << LL_ENDL;
@@ -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/llxml/llxmlparser.cpp b/indra/llxml/llxmlparser.cpp
index e2c7d17e2a..8afd412cda 100644
--- a/indra/llxml/llxmlparser.cpp
+++ b/indra/llxml/llxmlparser.cpp
@@ -72,7 +72,7 @@ bool LLXmlParser::parseFile(const std::string &path)
bool success = true;
- LLFILE* file = LLFile::fopen(path, "rb"); /* Flawfinder: ignore */
+ LLFILE* file = LLFile::fopen(path, LLFILE_MODE("rb")); /* Flawfinder: ignore */
if( !file )
{
mAuxErrorString = llformat( "Couldn't open file %s", path.c_str());
@@ -388,7 +388,7 @@ int main()
{
char buf[1024];
- LLFILE* file = LLFile::fopen("test.xml", "rb");
+ LLFILE* file = LLFile::fopen("test.xml", LLFILE_MODE("rb"));
if( !file )
{
return 1;
diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp
index 4192e029c5..e15117fc29 100644
--- a/indra/llxml/tests/llcontrol_test.cpp
+++ b/indra/llxml/tests/llcontrol_test.cpp
@@ -69,7 +69,7 @@ namespace tut
LLFile::remove(filename);
}
LLFile::remove(mTestConfigFile);
- LLFile::rmdir(mTestConfigDir);
+ LLFile::remove(mTestConfigDir);
}
void writeSettingsFile(const LLSD& config)
{
diff --git a/indra/media_plugins/base/media_plugin_base.exp b/indra/media_plugins/base/media_plugin_base.exp
index d8c7bb712a..d8c7bb712a 100755..100644
--- a/indra/media_plugins/base/media_plugin_base.exp
+++ b/indra/media_plugins/base/media_plugin_base.exp
diff --git a/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp b/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp
index 73ef7fc18c..73ef7fc18c 100755..100644
--- a/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp
+++ b/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp
diff --git a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp
index f8a48a91fd..f8a48a91fd 100755..100644
--- a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp
+++ b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp
diff --git a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc
index e9b7196e51..e9b7196e51 100755..100644
--- a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc
+++ b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc
diff --git a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc
index 4859a34405..4859a34405 100755..100644
--- a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc
+++ b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 429dc57af3..4703009f54 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-7.2.3
+2026.01.0
diff --git a/indra/newview/app_settings/llsd.xsd b/indra/newview/app_settings/llsd.xsd
index 34612d9faa..34612d9faa 100755..100644
--- a/indra/newview/app_settings/llsd.xsd
+++ b/indra/newview/app_settings/llsd.xsd
diff --git a/indra/newview/app_settings/message.xml b/indra/newview/app_settings/message.xml
index dee3fd72dd..dee3fd72dd 100755..100644
--- a/indra/newview/app_settings/message.xml
+++ b/indra/newview/app_settings/message.xml
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index becd9001fe..9b1af327eb 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>
@@ -7368,7 +7379,7 @@
<key>Type</key>
<string>F32</string>
<key>Value</key>
- <real>32.0</real>
+ <real>48.0</real>
</map>
<key>RenderCPUBasis</key>
<map>
@@ -10162,6 +10173,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>RenderHighPrecisionPostProcess</key>
+ <map>
+ <key>Comment</key>
+ <string>Use 16-bit floating point buffers for post process rendering</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ReplaySession</key>
<map>
<key>Comment</key>
@@ -13895,7 +13917,7 @@
<key>WLSkyDetail</key>
<map>
<key>Comment</key>
- <string>Controls vertex detail on the WindLight sky. Lower numbers will give better performance and uglier skies.</string>
+ <string>[OBSOLETE]</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
index 8c51b4a36b..f5200719ae 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
@@ -30,9 +30,13 @@ out vec4 frag_data[4];
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
-in vec3 vary_CloudColorSun;
-in vec3 vary_CloudColorAmbient;
-in float vary_CloudDensity;
+// In
+in vec3 pos;
+
+in vec2 vary_texcoord0;
+in vec2 vary_texcoord1;
+in vec2 vary_texcoord2;
+in vec2 vary_texcoord3;
uniform sampler2D cloud_noise_texture;
uniform sampler2D cloud_noise_texture_next;
@@ -42,11 +46,26 @@ uniform vec3 cloud_pos_density2;
uniform float cloud_scale;
uniform float cloud_variance;
-in vec2 vary_texcoord0;
-in vec2 vary_texcoord1;
-in vec2 vary_texcoord2;
-in vec2 vary_texcoord3;
-in float altitude_blend_factor;
+uniform vec3 camPosLocal;
+
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 moonlight_color;
+uniform int sun_up_factor;
+uniform vec3 ambient_color;
+uniform vec3 blue_horizon;
+uniform vec3 blue_density;
+uniform float haze_horizon;
+uniform float haze_density;
+
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float max_y;
+
+uniform vec3 glow;
+uniform float sun_moon_glow_factor;
+
+uniform vec3 cloud_color;
vec4 cloudNoise(vec2 uv)
{
@@ -58,21 +77,111 @@ vec4 cloudNoise(vec2 uv)
void main()
{
+ if (cloud_scale < 0.001)
+ {
+ discard;
+ }
+
// Set variables
vec2 uv1 = vary_texcoord0.xy;
vec2 uv2 = vary_texcoord1.xy;
-
- vec3 cloudColorSun = vary_CloudColorSun;
- vec3 cloudColorAmbient = vary_CloudColorAmbient;
- float cloudDensity = vary_CloudDensity;
vec2 uv3 = vary_texcoord2.xy;
vec2 uv4 = vary_texcoord3.xy;
- if (cloud_scale < 0.001)
+ // Get relative position
+ vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+ float altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
+
+ // Set altitude
+ if (rel_pos.y > 0)
{
- discard;
+ rel_pos *= (max_y / rel_pos.y);
+ }
+ if (rel_pos.y < 0)
+ {
+ altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
+ rel_pos *= (-32000. / rel_pos.y);
}
+ // Can normalize then
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
+
+ // Initialize temp variables
+ vec3 sunlight = sunlight_color;
+ vec3 light_atten;
+
+ // Sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
+
+ // Calculate relative weights
+ vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
+ vec3 blue_weight = blue_density / combined_haze;
+ vec3 haze_weight = haze_density / combined_haze;
+
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Distance
+ float density_dist = rel_pos_len * density_multiplier;
+
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist);
+
+ // Compute haze glow
+ float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ haze_glow *= sun_moon_glow_factor;
+
+ // Add "minimum anti-solar illumination"
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+ // Increase ambient when there are more clouds
+ vec3 tmpAmbient = ambient_color;
+ tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= (1. - cloud_shadow);
+
+ // Haze color below cloud
+ vec3 additiveColorBelowCloud =
+ (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+
+ // CLOUDS
+ sunlight = sunlight_color;
+ off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Cloud color out
+ vec3 cloudColorSun = (sunlight * haze_glow) * cloud_color;
+ vec3 cloudColorAmbient = tmpAmbient * cloud_color;
+
+ // Attenuate cloud color by atmosphere
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
+ cloudColorSun *= combined_haze;
+ cloudColorAmbient *= combined_haze;
+ vec3 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+
+ // Make a nice cloud density based on the cloud_shadow value that was passed in.
+ float cloudDensity = 2. * (cloud_shadow - 0.25);
+
+ // Combine these to minimize register use
+ cloudColorAmbient += oHazeColorBelowCloud;
+
+ // Cloud Fragment
vec2 disturbance = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index c019b5606a..89fbe38af0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -1,5 +1,5 @@
/**
- * @file WLCloudsV.glsl
+ * @file class1/deferred/cloudsV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -33,38 +33,15 @@ in vec2 texcoord0;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-out vec3 vary_CloudColorSun;
-out vec3 vary_CloudColorAmbient;
-out float vary_CloudDensity;
+out vec3 pos;
out vec2 vary_texcoord0;
out vec2 vary_texcoord1;
out vec2 vary_texcoord2;
out vec2 vary_texcoord3;
-out float altitude_blend_factor;
// Inputs
-uniform vec3 camPosLocal;
-
uniform vec3 lightnorm;
-uniform vec3 sunlight_color;
-uniform vec3 moonlight_color;
-uniform int sun_up_factor;
-uniform vec3 ambient_color;
-uniform vec3 blue_horizon;
-uniform vec3 blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
-
-uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float max_y;
-
-uniform vec3 glow;
-uniform float sun_moon_glow_factor;
-
-uniform vec3 cloud_color;
-
uniform float cloud_scale;
// NOTE: Keep these in sync!
@@ -76,6 +53,7 @@ uniform float cloud_scale;
void main()
{
// World / view / projection
+ pos = position.xyz;
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
// Texture coords
@@ -92,102 +70,4 @@ void main()
vary_texcoord2 = vary_texcoord0 * 16.;
vary_texcoord3 = vary_texcoord1 * 16.;
-
- // Get relative position
- vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
-
- altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
-
- // Set altitude
- if (rel_pos.y > 0)
- {
- rel_pos *= (max_y / rel_pos.y);
- }
- if (rel_pos.y < 0)
- {
- altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
- rel_pos *= (-32000. / rel_pos.y);
- }
-
- // Can normalize then
- vec3 rel_pos_norm = normalize(rel_pos);
- float rel_pos_len = length(rel_pos);
-
- // Initialize temp variables
- vec3 sunlight = sunlight_color;
- vec3 light_atten;
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
-
- // Calculate relative weights
- vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
- vec3 blue_weight = blue_density / combined_haze;
- vec3 haze_weight = haze_density / combined_haze;
-
- // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
- float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
- sunlight *= exp(-light_atten * off_axis);
-
- // Distance
- float density_dist = rel_pos_len * density_multiplier;
-
- // Transparency (-> combined_haze)
- // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
- // compiler gets confused.
- combined_haze = exp(-combined_haze * density_dist);
-
- // Compute haze glow
- float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
- // haze_glow is 0 at the sun and increases away from sun
- haze_glow = max(haze_glow, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- haze_glow *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- haze_glow = pow(haze_glow, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- haze_glow *= sun_moon_glow_factor;
-
- // Add "minimum anti-solar illumination"
- // For sun, add to glow. For moon, remove glow entirely. SL-13768
- haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
-
- // Increase ambient when there are more clouds
- vec3 tmpAmbient = ambient_color;
- tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
-
- // Dim sunlight by cloud shadow percentage
- sunlight *= (1. - cloud_shadow);
-
- // Haze color below cloud
- vec3 additiveColorBelowCloud =
- (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
-
- // CLOUDS
- sunlight = sunlight_color;
- off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
- sunlight *= exp(-light_atten * off_axis);
-
- // Cloud color out
- vary_CloudColorSun = (sunlight * haze_glow) * cloud_color;
- vary_CloudColorAmbient = tmpAmbient * cloud_color;
-
- // Attenuate cloud color by atmosphere
- combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
- vary_CloudColorSun *= combined_haze;
- vary_CloudColorAmbient *= combined_haze;
- vec3 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
-
- // Make a nice cloud density based on the cloud_shadow value that was passed in.
- vary_CloudDensity = 2. * (cloud_shadow - 0.25);
-
- // Combine these to minimize register use
- vary_CloudColorAmbient += oHazeColorBelowCloud;
-
- // needs this to compile on mac
- //vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
-
- // END CLOUDS
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
index 7639a5e6fc..b70d1db499 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -23,13 +23,14 @@
* $/LicenseInfo$
*/
+// Outputs
+out vec4 frag_data[4];
+
// Inputs
-in vec3 vary_HazeColor;
-in float vary_LightNormPosDot;
+in vec3 pos;
#ifdef HAS_HDRI
in vec4 vary_position;
-in vec3 vary_rel_pos;
uniform float sky_hdr_scale;
uniform float hdri_split_screen;
uniform mat3 env_mat;
@@ -43,7 +44,27 @@ uniform float moisture_level;
uniform float droplet_radius;
uniform float ice_level;
-out vec4 frag_data[4];
+uniform vec3 camPosLocal;
+
+uniform vec3 lightnorm;
+uniform vec3 sunlight_color;
+uniform vec3 moonlight_color;
+uniform int sun_up_factor;
+uniform vec3 ambient_color;
+uniform vec3 blue_horizon;
+uniform vec3 blue_density;
+uniform float haze_horizon;
+uniform float haze_density;
+
+uniform float cloud_shadow;
+uniform float density_multiplier;
+uniform float distance_multiplier;
+uniform float max_y;
+
+uniform vec3 glow;
+uniform float sun_moon_glow_factor;
+
+uniform int cube_snapshot;
vec3 srgb_to_linear(vec3 c);
vec3 linear_to_srgb(vec3 c);
@@ -83,12 +104,25 @@ vec3 halo22(float d)
void main()
{
+ // Get relative position
+ vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+ // Adj position vector to clamp altitude
+ if (rel_pos.y > 0.)
+ {
+ rel_pos *= (max_y / rel_pos.y);
+ }
+ if (rel_pos.y < 0.)
+ {
+ rel_pos *= (-32000. / rel_pos.y);
+ }
+
vec3 color;
#ifdef HAS_HDRI
vec3 frag_coord = vary_position.xyz/vary_position.w;
if (-frag_coord.x > ((1.0-hdri_split_screen)*2.0-1.0))
{
- vec3 pos = normalize(vary_rel_pos);
+ vec3 pos = normalize(rel_pos);
pos = env_mat * pos;
vec2 texCoord = vec2(atan(pos.z, pos.x) + PI, acos(pos.y)) / vec2(2.0 * PI, PI);
color = textureLod(environmentMap, texCoord.xy, 0).rgb * sky_hdr_scale;
@@ -99,15 +133,75 @@ void main()
else
#endif
{
- // Potential Fill-rate optimization. Add cloud calculation
- // back in and output alpha of 0 (so that alpha culling kills
- // the fragment) if the sky wouldn't show up because the clouds
- // are fully opaque.
+ // Normalized
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
+
+ // Grab this value and pass to frag shader for rainbows
+ float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz);
+
+ // Initialize temp variables
+ vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color * 0.7; //magic 0.7 to match legacy color
+
+ // Sunlight attenuation effect (hue and brightness) due to atmosphere
+ // this is used later for sunlight modulation at various altitudes
+ vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
+
+ // Calculate relative weights
+ vec3 combined_haze = max(abs(blue_density) + vec3(abs(haze_density)), vec3(1e-6));
+ vec3 blue_weight = blue_density / combined_haze;
+ vec3 haze_weight = haze_density / combined_haze;
+
+ // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+ float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+ sunlight *= exp(-light_atten * off_axis);
+
+ // Distance
+ float density_dist = rel_pos_len * density_multiplier;
+
+ // Transparency (-> combined_haze)
+ // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+ // compiler gets confused.
+ combined_haze = exp(-combined_haze * density_dist);
+
+ // Compute haze glow
+ float haze_glow = 1.0 - rel_pos_lightnorm_dot;
+ // haze_glow is 0 at the sun and increases away from sun
+ haze_glow = max(haze_glow, .001);
+ // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+ haze_glow *= glow.x;
+ // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+ haze_glow = pow(haze_glow, glow.z);
+ // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+ // Add "minimum anti-solar illumination"
+ // For sun, add to glow. For moon, remove glow entirely. SL-13768
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
+
+ // Haze color above cloud
+ color = (blue_horizon * blue_weight * (sunlight + ambient_color)
+ + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
+
+ // Final atmosphere additive
+ color *= (1. - combined_haze);
+
+ // Increase ambient when there are more clouds
+ vec3 ambient = ambient_color + max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+
+ // Dim sunlight by cloud shadow percentage
+ sunlight *= max(0.0, (1. - cloud_shadow));
+
+ // Haze color below cloud
+ vec3 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)
+ + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));
+
+ // Attenuate cloud color by atmosphere
+ combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
- color = vary_HazeColor;
+ // At horizon, blend high altitude sky color towards the darker color below the clouds
+ color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
- float rel_pos_lightnorm = vary_LightNormPosDot;
- float optic_d = rel_pos_lightnorm;
+ float optic_d = rel_pos_lightnorm_dot;
vec3 halo_22 = halo22(optic_d);
color.rgb += rainbow(optic_d);
color.rgb += halo_22;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index ea00d240df..836ad66098 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -1,5 +1,5 @@
/**
- * @file WLSkyV.glsl
+ * @file class1/deferred/skyV.glsl
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -32,36 +32,13 @@ in vec3 position;
///////////////////////////////////////////////////////////////////////////////
// Output parameters
-out vec3 vary_HazeColor;
-out float vary_LightNormPosDot;
+out vec3 pos;
#ifdef HAS_HDRI
out vec4 vary_position;
-out vec3 vary_rel_pos;
#endif
// Inputs
-uniform vec3 camPosLocal;
-
-uniform vec3 lightnorm;
-uniform vec3 sunlight_color;
-uniform vec3 moonlight_color;
-uniform int sun_up_factor;
-uniform vec3 ambient_color;
-uniform vec3 blue_horizon;
-uniform vec3 blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
-
-uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float distance_multiplier;
-uniform float max_y;
-
-uniform vec3 glow;
-uniform float sun_moon_glow_factor;
-
-uniform int cube_snapshot;
// NOTE: Keep these in sync!
// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
@@ -70,97 +47,13 @@ uniform int cube_snapshot;
void main()
{
// World / view / projection
- vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
-
- gl_Position = pos;
-
- // Get relative position
- vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
-
-#ifdef HAS_HDRI
- vary_rel_pos = rel_pos;
- vary_position = pos;
-#endif
-
- // Adj position vector to clamp altitude
- if (rel_pos.y > 0.)
- {
- rel_pos *= (max_y / rel_pos.y);
- }
- if (rel_pos.y < 0.)
- {
- rel_pos *= (-32000. / rel_pos.y);
- }
-
- // Normalized
- vec3 rel_pos_norm = normalize(rel_pos);
- float rel_pos_len = length(rel_pos);
-
- // Grab this value and pass to frag shader for rainbows
- float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz);
- vary_LightNormPosDot = rel_pos_lightnorm_dot;
-
- // Initialize temp variables
- vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color * 0.7; //magic 0.7 to match legacy color
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
-
- // Calculate relative weights
- vec3 combined_haze = max(abs(blue_density) + vec3(abs(haze_density)), vec3(1e-6));
- vec3 blue_weight = blue_density / combined_haze;
- vec3 haze_weight = haze_density / combined_haze;
-
- // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
- float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
- sunlight *= exp(-light_atten * off_axis);
-
- // Distance
- float density_dist = rel_pos_len * density_multiplier;
-
- // Transparency (-> combined_haze)
- // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
- // compiler gets confused.
- combined_haze = exp(-combined_haze * density_dist);
-
- // Compute haze glow
- float haze_glow = 1.0 - rel_pos_lightnorm_dot;
- // haze_glow is 0 at the sun and increases away from sun
- haze_glow = max(haze_glow, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- haze_glow *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- haze_glow = pow(haze_glow, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- // Add "minimum anti-solar illumination"
- // For sun, add to glow. For moon, remove glow entirely. SL-13768
- haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
-
- // Haze color above cloud
- vec3 color = (blue_horizon * blue_weight * (sunlight + ambient_color)
- + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
-
- // Final atmosphere additive
- color *= (1. - combined_haze);
-
- // Increase ambient when there are more clouds
- vec3 ambient = ambient_color + max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
-
- // Dim sunlight by cloud shadow percentage
- sunlight *= max(0.0, (1. - cloud_shadow));
-
- // Haze color below cloud
- vec3 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)
- + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));
+ pos = position.xyz;
- // Attenuate cloud color by atmosphere
- combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
+ vec4 transformed_pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
- // At horizon, blend high altitude sky color towards the darker color below the clouds
- color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
+ gl_Position = transformed_pos;
- // Haze color above cloud
- vary_HazeColor = color;
+ #ifdef HAS_HDRI
+ vary_position = transformed_pos;
+ #endif
}
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index eca58938cf..21cbf259df 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 75
+version 76
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -56,7 +56,6 @@ RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
WindLightUseAtmosShaders 1 1
-WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
RenderCompressTextures 1 1
@@ -87,6 +86,7 @@ RenderTonemapMix 1 1
RenderDisableVintageMode 1 1
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Low Graphics Settings
@@ -113,7 +113,6 @@ RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 0
RenderFSAASamples 1 0
RenderScreenSpaceReflections 1 0
@@ -130,6 +129,7 @@ RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
RenderReflectionProbeCount 1 1
+RenderHighPrecisionPostProcess 1 0
//
// Medium Low Graphics Settings
@@ -156,7 +156,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 0
RenderFSAASamples 1 0
RenderScreenSpaceReflections 1 0
@@ -173,6 +172,7 @@ RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
RenderReflectionProbeCount 1 32
+RenderHighPrecisionPostProcess 1 0
//
// Medium Graphics Settings (standard)
@@ -197,7 +197,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.25
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 1
RenderReflectionsEnabled 1 1
@@ -215,6 +214,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
+RenderHighPrecisionPostProcess 1 0
//
// Medium High Graphics Settings
@@ -239,7 +239,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.375
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 1
RenderReflectionsEnabled 1 1
@@ -257,6 +256,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
+RenderHighPrecisionPostProcess 1 0
//
// High Graphics Settings (SSAO + sun shadows)
@@ -281,7 +281,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.5
RenderDeferredSSAO 1 1
RenderShadowDetail 1 1
-WLSkyDetail 1 96
RenderFSAAType 1 2
RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
@@ -299,6 +298,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 128
+RenderHighPrecisionPostProcess 1 0
//
// High Ultra Graphics Settings (SSAO + all shadows)
@@ -323,7 +323,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.75
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
-WLSkyDetail 1 96
RenderFSAAType 1 2
RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
@@ -341,6 +340,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Ultra graphics (REALLY PURTY!)
@@ -363,7 +363,6 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
-WLSkyDetail 1 128
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderFSAAType 1 2
@@ -383,6 +382,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Class Unknown Hardware (unknown)
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index a160161ef1..5d2819169e 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 34
+version 35
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -56,7 +56,6 @@ RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
WindLightUseAtmosShaders 1 1
-WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
RenderCompressTextures 1 1
@@ -87,6 +86,7 @@ RenderTonemapMix 1 1
RenderDisableVintageMode 1 1
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Low Graphics Settings
@@ -113,7 +113,6 @@ RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 0
RenderFSAASamples 1 0
RenderScreenSpaceReflections 1 0
@@ -130,6 +129,7 @@ RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
RenderReflectionProbeCount 1 1
+RenderHighPrecisionPostProcess 1 0
//
// Medium Low Graphics Settings
@@ -156,7 +156,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 0
RenderFSAASamples 1 0
RenderScreenSpaceReflections 1 0
@@ -173,6 +172,7 @@ RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
RenderReflectionProbeCount 1 32
+RenderHighPrecisionPostProcess 1 0
//
// Medium Graphics Settings (standard)
@@ -197,7 +197,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.25
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 1
RenderReflectionsEnabled 1 1
@@ -215,6 +214,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
+RenderHighPrecisionPostProcess 1 0
//
// Medium High Graphics Settings
@@ -239,7 +239,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.375
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 1
RenderReflectionsEnabled 1 1
@@ -257,6 +256,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
+RenderHighPrecisionPostProcess 1 0
//
// High Graphics Settings (SSAO + sun shadows)
@@ -281,7 +281,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.5
RenderDeferredSSAO 1 1
RenderShadowDetail 1 1
-WLSkyDetail 1 96
RenderFSAAType 1 2
RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
@@ -299,6 +298,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 128
+RenderHighPrecisionPostProcess 1 0
//
// High Ultra Graphics Settings (SSAO + all shadows)
@@ -323,7 +323,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.75
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
-WLSkyDetail 1 96
RenderFSAAType 1 2
RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
@@ -341,6 +340,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Ultra graphics (REALLY PURTY!)
@@ -363,7 +363,6 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
-WLSkyDetail 1 128
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderFSAAType 1 2
@@ -383,6 +382,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Class Unknown Hardware (unknown)
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index b75df5e3f2..7bb4fb6dd0 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 74
+version 75
// The version number above should be incremented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -54,7 +54,6 @@ RenderVolumeLODFactor 1 2.0
UseStartScreen 1 1
UseOcclusion 1 1
WindLightUseAtmosShaders 1 1
-WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
RenderCompressTextures 1 1
@@ -87,6 +86,7 @@ RenderDisableVintageMode 1 1
RenderDownScaleMethod 1 0
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Low Graphics Settings
@@ -111,7 +111,6 @@ RenderTreeLODFactor 1 0
RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 0
RenderFSAASamples 1 0
RenderReflectionsEnabled 1 0
@@ -130,6 +129,7 @@ RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 512
RenderReflectionProbeCount 1 1
+RenderHighPrecisionPostProcess 1 0
//
// Medium Low Graphics Settings
@@ -154,7 +154,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.125
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 0
RenderFSAASamples 1 0
RenderReflectionsEnabled 1 1
@@ -173,6 +172,7 @@ RenderTonemapMix 1 0.7
RenderDisableVintageMode 1 0
RenderMaxTextureResolution 1 1024
RenderReflectionProbeCount 1 32
+RenderHighPrecisionPostProcess 1 0
//
// Medium Graphics Settings (standard)
@@ -197,7 +197,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.25
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 0
RenderReflectionsEnabled 1 1
@@ -215,6 +214,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
+RenderHighPrecisionPostProcess 1 0
//
// Medium High Graphics Settings
@@ -239,7 +239,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.375
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 1
RenderReflectionsEnabled 1 1
@@ -257,6 +256,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 64
+RenderHighPrecisionPostProcess 1 0
//
// High Graphics Settings (SSAO + sun shadows)
@@ -281,7 +281,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.5
RenderDeferredSSAO 1 1
RenderShadowDetail 1 1
-WLSkyDetail 1 96
RenderFSAAType 1 1
RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
@@ -299,6 +298,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 128
+RenderHighPrecisionPostProcess 1 0
//
// High Ultra Graphics Settings (SSAO + all shadows)
@@ -323,7 +323,6 @@ RenderTreeLODFactor 1 0.5
RenderVolumeLODFactor 1 1.75
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
-WLSkyDetail 1 96
RenderFSAAType 1 2
RenderFSAASamples 1 2
RenderReflectionsEnabled 1 1
@@ -341,6 +340,7 @@ RenderTonemapType 1 1
RenderTonemapMix 1 0.7
RenderMaxTextureResolution 1 2048
RenderReflectionProbeCount 1 256
+RenderHighPrecisionPostProcess 1 1
//
// Ultra graphics (REALLY PURTY!)
@@ -363,7 +363,6 @@ RenderTransparentWater 1 1
RenderTreeLODFactor 1 1.0
RenderVolumeLODFactor 1 2.0
WindLightUseAtmosShaders 1 1
-WLSkyDetail 1 128
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderFSAAType 1 2
diff --git a/indra/newview/installers/darwin/dmg-cleanup.applescript b/indra/newview/installers/darwin/dmg-cleanup.applescript
index 8a71b392f9..8a71b392f9 100755..100644
--- a/indra/newview/installers/darwin/dmg-cleanup.applescript
+++ b/indra/newview/installers/darwin/dmg-cleanup.applescript
diff --git a/indra/newview/installers/darwin/release-dmg/Applications-alias.r b/indra/newview/installers/darwin/release-dmg/Applications-alias.r
index f9be0536c6..f9be0536c6 100755..100644
--- a/indra/newview/installers/darwin/release-dmg/Applications-alias.r
+++ b/indra/newview/installers/darwin/release-dmg/Applications-alias.r
diff --git a/indra/newview/installers/darwin/release-dmg/_DS_Store b/indra/newview/installers/darwin/release-dmg/_DS_Store
index 747ca961d8..747ca961d8 100755..100644
--- a/indra/newview/installers/darwin/release-dmg/_DS_Store
+++ b/indra/newview/installers/darwin/release-dmg/_DS_Store
Binary files differ
diff --git a/indra/newview/installers/windows/lang_de.nsi b/indra/newview/installers/windows/lang_de.nsi
index 7cc70e4c76..7cc70e4c76 100755..100644
--- a/indra/newview/installers/windows/lang_de.nsi
+++ b/indra/newview/installers/windows/lang_de.nsi
diff --git a/indra/newview/installers/windows/lang_es.nsi b/indra/newview/installers/windows/lang_es.nsi
index 364cc9f67e..364cc9f67e 100755..100644
--- a/indra/newview/installers/windows/lang_es.nsi
+++ b/indra/newview/installers/windows/lang_es.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_fr.nsi b/indra/newview/installers/windows/lang_fr.nsi
index 2f34c0c87a..2f34c0c87a 100755..100644
--- a/indra/newview/installers/windows/lang_fr.nsi
+++ b/indra/newview/installers/windows/lang_fr.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_it.nsi b/indra/newview/installers/windows/lang_it.nsi
index 51214d3a9c..51214d3a9c 100755..100644
--- a/indra/newview/installers/windows/lang_it.nsi
+++ b/indra/newview/installers/windows/lang_it.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_ja.nsi b/indra/newview/installers/windows/lang_ja.nsi
index 296703d1a3..296703d1a3 100755..100644
--- a/indra/newview/installers/windows/lang_ja.nsi
+++ b/indra/newview/installers/windows/lang_ja.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi
index 542c8654b5..542c8654b5 100755..100644
--- a/indra/newview/installers/windows/lang_pt-br.nsi
+++ b/indra/newview/installers/windows/lang_pt-br.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi
index 4e53a4957d..4e53a4957d 100755..100644
--- a/indra/newview/installers/windows/lang_ru.nsi
+++ b/indra/newview/installers/windows/lang_ru.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi
index bae5029ad1..bae5029ad1 100755..100644
--- a/indra/newview/installers/windows/lang_tr.nsi
+++ b/indra/newview/installers/windows/lang_tr.nsi
Binary files differ
diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi
index 0985663041..0985663041 100755..100644
--- a/indra/newview/installers/windows/lang_zh.nsi
+++ b/indra/newview/installers/windows/lang_zh.nsi
Binary files differ
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/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index 409671d939..23a4effd87 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -26,7 +26,7 @@
#import "llappdelegate-objc.h"
#if defined(LL_BUGSPLAT)
-#include <boost/filesystem.hpp>
+#include <filesystem>
#include <vector>
@import CrashReporter;
@import HockeySDK;
@@ -252,7 +252,7 @@
if(!secondLogPath.empty())
{
- boost::filesystem::remove(secondLogPath);
+ std::filesystem::remove(secondLogPath);
}
clearDumpLogsDir();
}
@@ -326,7 +326,7 @@ struct AttachmentInfo
{
AttachmentInfo(const std::string& path, const std::string& type):
pathname(path),
- basename(boost::filesystem::path(path).filename().string()),
+ basename(std::filesystem::path(path).filename().string()),
mimetype(type)
{}
@@ -361,7 +361,7 @@ struct AttachmentInfo
// the log data to a browser, so take this opportunity to rename the file
// from <base>.crash to <base>_log.txt
info[0].basename =
- boost::filesystem::path(info[0].pathname).stem().string() + "_log.txt";
+ std::filesystem::path(info[0].pathname).stem().string() + "_log.txt";
infos("attachmentsForBugsplatStartupManager attaching log " + info[0].basename);
NSMutableArray *attachments = [[NSMutableArray alloc] init];
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 5351ed9f08..1a9bda6a06 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2268,7 +2268,7 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
LLAppViewer::instance()->writeDebugInfo();
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
- if (!LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
+ if (!LLFile::isfile(error_marker_file))
{
// If marker doesn't exist, create a marker with llerror code for next launch
// otherwise don't override existing file
@@ -2455,7 +2455,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;
}
@@ -3031,13 +3034,11 @@ void LLAppViewer::initStrings()
}
else
{
- llstat st;
- int rc = LLFile::stat(strings_path_full, &st);
- if (rc != 0)
+ if (!LLFile::exists(strings_path_full))
{
- crash_reason = "The file '" + strings_path_full + "' failed to get status. Error code: " + std::to_string(rc);
+ crash_reason = "The file '" + strings_path_full + "' doesn't seem to exist";
}
- else if (S_ISDIR(st.st_mode))
+ else if (LLFile::isdir(strings_path_full))
{
crash_reason = "The filename '" + strings_path_full + "' is a directory name";
}
@@ -3892,7 +3893,7 @@ void LLAppViewer::processMarkerFiles()
bool marker_is_same_version = true;
// first, look for the marker created at startup and deleted on a clean exit
mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
- if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB))
+ if (LLFile::isfile(mMarkerFileName))
{
// File exists...
// first, read it to see if it was created by the same version (we need this later)
@@ -3984,7 +3985,7 @@ void LLAppViewer::processMarkerFiles()
// check for any last exec event report based on whether or not it happened during logout
// (the logout marker is created when logout begins)
std::string logout_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME);
- if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
+ if(LLFile::isfile(logout_marker_file))
{
if (markerIsSameVersion(logout_marker_file))
{
@@ -3996,11 +3997,11 @@ void LLAppViewer::processMarkerFiles()
{
LL_INFOS("MarkerFile") << "Logout crash marker '"<< logout_marker_file << "' found, but versions did not match" << LL_ENDL;
}
- LLAPRFile::remove(logout_marker_file);
+ LLFile::remove(logout_marker_file);
}
// and last refine based on whether or not a marker created during a non-llerr crash is found
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
- if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
+ if(LLFile::isfile(error_marker_file))
{
S32 marker_code = getMarkerErrorCode(error_marker_file);
if (marker_code >= 0)
@@ -4025,7 +4026,7 @@ void LLAppViewer::processMarkerFiles()
{
LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' marker found, but versions did not match" << LL_ENDL;
}
- LLAPRFile::remove(error_marker_file);
+ LLFile::remove(error_marker_file);
}
#if LL_DARWIN
@@ -4052,7 +4053,7 @@ void LLAppViewer::removeMarkerFiles()
if (mMarkerFile.getFileHandle())
{
mMarkerFile.close() ;
- LLAPRFile::remove( mMarkerFileName );
+ LLFile::remove( mMarkerFileName );
LL_DEBUGS("MarkerFile") << "removed exec marker '"<<mMarkerFileName<<"'"<< LL_ENDL;
}
else
@@ -4063,7 +4064,7 @@ void LLAppViewer::removeMarkerFiles()
if (mLogoutMarkerFile.getFileHandle())
{
mLogoutMarkerFile.close();
- LLAPRFile::remove( mLogoutMarkerFileName );
+ LLFile::remove( mLogoutMarkerFileName );
LL_DEBUGS("MarkerFile") << "removed logout marker '"<<mLogoutMarkerFileName<<"'"<< LL_ENDL;
}
else
@@ -4285,7 +4286,7 @@ void LLAppViewer::migrateCacheDirectory()
LLFile::remove(ds_store);
}
#endif
- if (LLFile::rmdir(old_cache_dir) != 0)
+ if (LLFile::remove(old_cache_dir) != 0)
{
LL_WARNS() << "could not delete old cache directory " << old_cache_dir << LL_ENDL;
}
@@ -4502,7 +4503,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::remove(cache_dir);
+ }
}
std::string LLAppViewer::getSecondLifeTitle() const
@@ -5436,7 +5449,7 @@ void LLAppViewer::createErrorMarker(eLastExecEvent error_code) const
bool LLAppViewer::errorMarkerExists() const
{
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
- return LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB);
+ return LLFile::isfile(error_marker_file);
}
void LLAppViewer::outOfMemorySoftQuit()
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/llconversationlog.cpp b/indra/newview/llconversationlog.cpp
index 4a4985d8ac..bfcc2e4182 100644
--- a/indra/newview/llconversationlog.cpp
+++ b/indra/newview/llconversationlog.cpp
@@ -512,7 +512,7 @@ bool LLConversationLog::saveToFile(const std::string& filename)
return false;
}
- LLFILE* fp = LLFile::fopen(filename, "wb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("wb"));
if (!fp)
{
LL_WARNS() << "Couldn't open call log list" << filename << LL_ENDL;
@@ -556,7 +556,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
return false;
}
- LLFILE* fp = LLFile::fopen(filename, "rb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("rb"));
if (!fp)
{
LL_WARNS() << "Couldn't open call log list" << filename << LL_ENDL;
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/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 6c151351ff..a42972205a 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -114,7 +114,7 @@ void LLStandardBumpmap::addstandard()
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS
std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" );
- LLFILE* file = LLFile::fopen( file_name, "rt" ); /*Flawfinder: ignore*/
+ LLFILE* file = LLFile::fopen( file_name, LLFILE_MODE("rt") ); /*Flawfinder: ignore*/
if( !file )
{
LL_WARNS() << "Could not open std_bump <" << file_name << ">" << LL_ENDL;
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 37802fa175..b9c84c10cf 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -2372,7 +2372,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/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/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index 83abbb0357..83abbb0357 100755..100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp
index 7316d7617d..2a67e75fec 100644
--- a/indra/newview/llfloatermarketplace.cpp
+++ b/indra/newview/llfloatermarketplace.cpp
@@ -39,6 +39,26 @@ 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);
+ }
+}
+
// just to override LLFloaterWebContent
void LLFloaterMarketplace::onClose(bool app_quitting)
{
@@ -68,3 +88,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 b0f9ec2b19..3de3cf6070 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -475,7 +475,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));
@@ -517,18 +518,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
@@ -1341,6 +1342,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()
@@ -1501,7 +1508,7 @@ bool LLFloaterPreference::moveTranscriptsAndLog()
//Couldn't move the log and created a new directory so remove the new directory
if(madeDirectory)
{
- LLFile::rmdir(chatLogPath);
+ LLFile::remove(chatLogPath);
}
return false;
}
@@ -1527,7 +1534,7 @@ bool LLFloaterPreference::moveTranscriptsAndLog()
if(madeDirectory)
{
- LLFile::rmdir(chatLogPath);
+ LLFile::remove(chatLogPath);
}
return false;
@@ -2037,17 +2044,19 @@ void LLFloaterPreference::changed()
{
if (LLConversationLog::instance().getIsLoggingEnabled())
{
- getChild<LLButton>("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0);
+ getChild<LLButton>("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0);
}
else
{
// onClearLog clears list, then notifies changed() and only then clears file,
// so check presence of conversations before checking file, file will cleared later.
- llstat st;
- bool has_logs = LLConversationLog::instance().getConversations().size() > 0
- && LLFile::stat(LLConversationLog::instance().getFileName(), &st) == 0
- && S_ISREG(st.st_mode)
- && st.st_size > 0;
+ bool has_logs = false;
+ if (LLConversationLog::instance().getConversations().size() > 0)
+ {
+ std::filesystem::path file_path = fsyspath(LLConversationLog::instance().getFileName());
+ has_logs = LLFile::isfile(file_path)
+ && LLFile::size(file_path) > 0;
+ }
getChild<LLButton>("clear_log")->setEnabled(has_logs);
}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 831a650c45..aa958459c9 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -238,6 +238,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/llfloaterpreferencesgraphicsadvanced.cpp b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
index 96c2e1e1e4..8999a84c7e 100644
--- a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
+++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp
@@ -158,7 +158,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refresh()
updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail", true), getChild<LLTextBox>("AvatarPhysicsDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail", true), getChild<LLTextBox>("TerrainMeshDetailText", true));
updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess", true), getChild<LLTextBox>("PostProcessText", true));
- updateSliderText(getChild<LLSliderCtrl>("SkyMeshDetail", true), getChild<LLTextBox>("SkyMeshDetailText", true));
+ updateSliderText(getChild<LLSliderCtrl>("GlowResolution", true), getChild<LLTextBox>("GlowResolutionText", true));
LLAvatarComplexityControls::setIndirectControls();
setMaxNonImpostorsText(
gSavedSettings.getU32("RenderAvatarMaxNonImpostors"),
@@ -277,16 +277,11 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
LLTextBox* shadows_text = getChild<LLTextBox>("RenderShadowDetailText");
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
- LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
- LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
LLSliderCtrl* cas_slider = getChild<LLSliderCtrl>("RenderSharpness");
// disabled windlight
if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
{
- sky->setEnabled(false);
- sky_text->setEnabled(false);
-
//deferred needs windlight, disable deferred
ctrl_shadows->setEnabled(false);
ctrl_shadows->setValue(0);
@@ -350,12 +345,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
{
- // WindLight
- LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
- LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
- sky->setEnabled(true);
- sky_text->setEnabled(true);
-
bool enabled = true;
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
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/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index c3bc24c6b9..637871da0d 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -484,47 +484,47 @@ bool LLFloaterUIPreview::postBuild()
bool found_en_us = false;
std::string language_directory;
std::string xui_dir = get_xui_dir(); // directory containing localizations -- don't forget trailing delim
- mLanguageSelection->removeall(); // clear out anything temporarily in list from XML
+ mLanguageSelection->removeall(); // clear out anything temporarily in list from XML
LLDirIterator iter(xui_dir, "*");
- while(found) // for every directory
+ while (found) // for every directory
{
- if((found = iter.next(language_directory))) // get next directory
+ if ((found = iter.next(language_directory))) // get next directory
{
std::string full_path = gDirUtilp->add(xui_dir, language_directory);
- if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it
+ if (!LLFile::isdir(full_path.c_str())) // if it's not a directory, skip it
{
continue;
}
- if(strncmp("template",language_directory.c_str(),8) && -1 == language_directory.find(".")) // if it's not the template directory or a hidden directory
+ if (strncmp("template",language_directory.c_str(), 8) && -1 == language_directory.find(".")) // if it's not the template directory or a hidden directory
{
- if(!strncmp("en",language_directory.c_str(),5)) // remember if we've seen en, so we can make it default
+ if (!strncmp("en",language_directory.c_str(), 5)) // remember if we've seen en, so we can make it default
{
found_en_us = true;
}
else
{
- mLanguageSelection->add(std::string(language_directory)); // add it to the language selection dropdown menu
+ mLanguageSelection->add(std::string(language_directory)); // add it to the language selection dropdown menu
mLanguageSelection_2->add(std::string(language_directory));
}
}
}
}
- if(found_en_us)
+ if (found_en_us)
{
- mLanguageSelection->add(std::string("en"),ADD_TOP); // make en first item if we found it
- mLanguageSelection_2->add(std::string("en"),ADD_TOP);
+ mLanguageSelection->add(std::string("en"), ADD_TOP); // make en first item if we found it
+ mLanguageSelection_2->add(std::string("en"), ADD_TOP);
}
else
{
std::string warning = std::string("No EN localization found; check your XUI directories!");
popupAndPrintWarning(warning);
}
- mLanguageSelection->selectFirstItem(); // select the first item
+ mLanguageSelection->selectFirstItem(); // select the first item
mLanguageSelection_2->selectFirstItem();
- refreshList(); // refresh the list of available floaters
+ refreshList(); // refresh the list of available floaters
return true;
}
@@ -574,7 +574,7 @@ void LLFloaterUIPreview::onClickExportSchema()
// std::string file_name(template_path + gDirUtilp->getDirDelimiter() + widget_name + ".rng");
- // LLFILE* rng_file = LLFile::fopen(file_name.c_str(), "w");
+ // LLFILE* rng_file = LLFile::fopen(file_name.c_str(), LLFILE_MODE("w"));
// {
// LLXMLNode::writeHeaderToFile(rng_file);
// const bool use_type_decorations = false;
@@ -892,8 +892,7 @@ void LLFloaterUIPreview::displayFloater(bool click, S32 ID)
// Add localization to title so user knows whether it's localized or defaulted to en
std::string full_path = getLocalizedDirectory() + path;
std::string floater_lang = "EN";
- llstat dummy;
- if(!LLFile::stat(full_path.c_str(), &dummy)) // if the file does not exist
+ if (LLFile::isfile(full_path.c_str())) // use localized language if the file exists
{
floater_lang = getLocStr(ID);
}
@@ -966,9 +965,8 @@ void LLFloaterUIPreview::onClickEditFloater()
}
file_path = getLocalizedDirectory() + file_name;
- // stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
- llstat dummy;
- if(LLFile::stat(file_path.c_str(), &dummy)) // if the file does not exist
+ // Does it exist? (Some localized versions may not have it when there are no diffs, and then we try to open a nonexistent file)
+ if (!LLFile::isfile(file_path.c_str())) // if the file does not exist
{
popupAndPrintWarning("No file for this floater exists in the selected localization. Opening the EN version instead.");
file_path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
@@ -1117,15 +1115,14 @@ void LLFloaterUIPreview::onClickToggleDiffHighlighting()
std::string path_in_textfield = mDiffPathTextBox->getText(); // get file path
bool error = false;
- if(std::string("") == path_in_textfield) // check for blank file
+ if(std::string("") == path_in_textfield) // check for blank file
{
std::string warning = "Unable to highlight differences because no file was provided; fill in the relevant text field";
popupAndPrintWarning(warning);
error = true;
}
- llstat dummy;
- if(LLFile::stat(path_in_textfield.c_str(), &dummy) && !error) // check if the file exists (empty check is reduntant but useful for the informative error message)
+ if (!LLFile::isfile(path_in_textfield.c_str()) && !error) // check if the file exists (empty check is redundant but useful for the informative error message)
{
std::string warning = std::string("Unable to highlight differences because an invalid path to a difference file was provided:\"") + path_in_textfield + "\"";
popupAndPrintWarning(warning);
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 03979edbc1..03979edbc1 100755..100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index cb1068943e..41d7d93528 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -901,6 +901,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
@@ -942,9 +975,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;
@@ -1034,33 +1064,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 2c3909cc79..c0c93f56e0 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..01ff01e233 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;
@@ -2745,7 +2754,7 @@ bool LLInventoryModel::loadSkeleton(
const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN;
std::string gzip_filename(inventory_filename);
gzip_filename.append(".gz");
- LLFILE* fp = LLFile::fopen(gzip_filename, "rb");
+ LLFILE* fp = LLFile::fopen(gzip_filename, LLFILE_MODE("rb"));
bool remove_inventory_file = false;
if (LLAppViewer::instance()->isSecondInstance())
{
@@ -4908,7 +4917,7 @@ bool decompress_file(const char* src_filename, const char* dst_filename)
// open the files
src = gzopen(src_filename, "rb");
if(!src) goto err_decompress;
- dst = LLFile::fopen(dst_filename, "wb");
+ dst = LLFile::fopen(dst_filename, LLFILE_MODE("wb"));
if(!dst) goto err_decompress;
// decompress.
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/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index 666ab4f5d0..c082c632f1 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -575,7 +575,7 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)
// Write the resulting XML to file
if (!output_node->isNull())
{
- LLFILE *fp = LLFile::fopen(filename, "w");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("w"));
if (fp != NULL)
{
LLXMLNode::writeHeaderToFile(fp);
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index a5ab5538e7..3567ca8e4a 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -31,8 +31,6 @@
/* own header */
#include "lllocalbitmaps.h"
-#include <boost/filesystem.hpp>
-
/* image compression headers. */
#include "llimagebmp.h"
#include "llimagetga.h"
@@ -40,11 +38,8 @@
#include "llimagejpeg.h"
#include "llimagepng.h"
-/* time headers */
-#include <time.h>
-#include <ctime>
-
/* misc headers */
+#include "fsyspath.h"
#include "llgltfmaterial.h"
#include "llscrolllistctrl.h"
#include "lllocaltextureobject.h"
@@ -190,15 +185,8 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
if (gDirUtilp->fileExists(mFilename))
{
// verifying that the file has indeed been modified
-
-#ifndef LL_WINDOWS
- const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename));
-#else
- const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(ll_convert<std::wstring>(mFilename)));
-#endif
- LLSD new_last_modified = asctime(localtime(&temp_time));
-
- if (mLastModified.asString() != new_last_modified.asString())
+ const std::filesystem::file_time_type new_last_modified = std::filesystem::last_write_time(fsyspath(mFilename));
+ if (mLastModified != new_last_modified)
{
/* loading the image file and decoding it, here is a critical point which,
if fails, invalidates the whole update (or unit creation) process. */
@@ -594,7 +582,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/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index 6c9d65e3b6..c4aaeae719 100644
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -32,6 +32,7 @@
#include "lleventtimer.h"
#include "llpointer.h"
#include "llwearabletype.h"
+#include <filesystem>
class LLScrollListCtrl;
class LLImageRaw;
@@ -99,7 +100,7 @@ class LLLocalBitmap
LLUUID mTrackingID;
LLUUID mWorldID;
bool mValid;
- LLSD mLastModified;
+ std::filesystem::file_time_type mLastModified;
EExtension mExtension;
ELinkStatus mLinkStatus;
S32 mUpdateRetries;
diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp
index aeae7cb56a..e9f2299be7 100644
--- a/indra/newview/lllocalgltfmaterials.cpp
+++ b/indra/newview/lllocalgltfmaterials.cpp
@@ -30,13 +30,8 @@
/* own header */
#include "lllocalgltfmaterials.h"
-#include <boost/filesystem.hpp>
-
-/* time headers */
-#include <time.h>
-#include <ctime>
-
/* misc headers */
+#include "fsyspath.h"
#include "llgltfmateriallist.h"
#include "llimage.h"
#include "llinventoryicon.h"
@@ -128,15 +123,8 @@ bool LLLocalGLTFMaterial::updateSelf()
if (gDirUtilp->fileExists(mFilename))
{
// verifying that the file has indeed been modified
-
-#ifndef LL_WINDOWS
- const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(mFilename));
-#else
- const std::time_t temp_time = boost::filesystem::last_write_time(boost::filesystem::path(ll_convert<std::wstring>(mFilename)));
-#endif
- LLSD new_last_modified = asctime(localtime(&temp_time));
-
- if (mLastModified.asString() != new_last_modified.asString())
+ const std::filesystem::file_time_type new_last_modified = std::filesystem::last_write_time(fsyspath(mFilename));
+ if (mLastModified != new_last_modified)
{
if (loadMaterial())
{
diff --git a/indra/newview/lllocalgltfmaterials.h b/indra/newview/lllocalgltfmaterials.h
index b806b54508..bf9a8c68ae 100644
--- a/indra/newview/lllocalgltfmaterials.h
+++ b/indra/newview/lllocalgltfmaterials.h
@@ -30,6 +30,7 @@
#include "lleventtimer.h"
#include "llpointer.h"
#include "llgltfmateriallist.h"
+#include <filesystem>
class LLScrollListCtrl;
class LLGLTFMaterial;
@@ -73,7 +74,7 @@ private: /* members */
std::string mShortName;
LLUUID mTrackingID;
LLUUID mWorldID;
- LLSD mLastModified;
+ std::filesystem::file_time_type mLastModified;
EExtension mExtension;
ELinkStatus mLinkStatus;
S32 mUpdateRetries;
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 30ea255e24..59f6993a0b 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -453,7 +453,7 @@ void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& m
// If we got here, we managed to stat the file.
// Open the file to read in binary mode to prevent interpreting other characters as EOF
- LLFILE* fptr = LLFile::fopen(log_file_name, "rb"); /*Flawfinder: ignore*/
+ LLFILE* fptr = LLFile::fopen(log_file_name, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!fptr)
{ // Ok, this is strange but not really tragic in the big picture of things
LL_WARNS("ChatHistory") << "Unable to read file " << log_file_name << " after stat was successful" << LL_ENDL;
@@ -890,7 +890,7 @@ bool LLLogChat::isAdHocTranscriptExist(std::string file_name)
bool LLLogChat::isTranscriptFileFound(std::string fullname)
{
bool result = false;
- LLFILE * filep = LLFile::fopen(fullname, "rb");
+ LLFILE * filep = LLFile::fopen(fullname, LLFILE_MODE("rb"));
if (NULL != filep)
{
if (makeLogFileName("chat") == fullname)
@@ -1183,7 +1183,7 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL
}
bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
- LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "rb");/*Flawfinder: ignore*/
+ LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), LLFILE_MODE("rb"));/*Flawfinder: ignore*/
if (!fptr)
{
@@ -1192,17 +1192,17 @@ void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LL
{
std::string old_name(file_name);
old_name.erase(old_name.size() - GROUP_CHAT_SUFFIX.size());
- fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), "rb");
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(old_name), LLFILE_MODE("rb"));
if (fptr)
{
fclose(fptr);
LLFile::copy(LLLogChat::makeLogFileName(old_name), LLLogChat::makeLogFileName(file_name));
}
- fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "rb");
+ fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), LLFILE_MODE("rb"));
}
if (!fptr)
{
- fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "rb");/*Flawfinder: ignore*/
+ fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!fptr)
{
mNewLoad = false;
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index d1d4641df3..dad04f4eab 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -845,7 +845,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",
@@ -1752,7 +1752,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 0ed1e01ff8..68739341e9 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/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 9157e34833..35d36affa2 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -589,7 +589,7 @@ bool LLMuteList::loadFromFile(const std::string& filename)
return false;
}
- LLFILE* fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!fp)
{
LL_WARNS() << "Couldn't open mute list " << filename << LL_ENDL;
@@ -653,7 +653,7 @@ bool LLMuteList::saveToFile(const std::string& filename)
return false;
}
- LLFILE* fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("wb")); /*Flawfinder: ignore*/
if (!fp)
{
LL_WARNS() << "Couldn't open mute list " << filename << LL_ENDL;
@@ -940,7 +940,7 @@ LLRenderMuteList::LLRenderMuteList()
bool LLRenderMuteList::saveToFile()
{
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt");
- LLFILE* fp = LLFile::fopen(filename, "wb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("wb"));
if (!fp)
{
LL_WARNS() << "Couldn't open render mute list file: " << filename << LL_ENDL;
@@ -963,7 +963,7 @@ bool LLRenderMuteList::saveToFile()
bool LLRenderMuteList::loadFromFile()
{
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "render_mute_settings.txt");
- LLFILE* fp = LLFile::fopen(filename, "rb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("rb"));
if (!fp)
{
LL_WARNS() << "Couldn't open render mute list file: " << filename << LL_ENDL;
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 2bb6af24bc..2bb6af24bc 100755..100644
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
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..00b592d86e 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);
@@ -297,8 +298,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
childSetAction("connect_btn", onClickConnect, this);
- LLButton* def_btn = getChild<LLButton>("connect_btn");
- setDefaultBtn(def_btn);
+ mLoginBtn = getChild<LLButton>("connect_btn");
+ setDefaultBtn(mLoginBtn);
std::string channel = LLVersionInfo::instance().getChannel();
std::string version = stringize(LLVersionInfo::instance().getShortVersion(), " (",
@@ -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/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/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 9a991727b2..cecda23e7b 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -575,8 +575,7 @@ void LLPreviewNotecard::syncExternal()
{
// Sync with external editor.
std::string tmp_file = getTmpFileName();
- llstat s;
- if (LLFile::stat(tmp_file, &s) == 0) // file exists
+ if (LLFile::isfile(tmp_file)) // file exists
{
if (mLiveFile) mLiveFile->ignoreNextUpdate();
writeToFile(tmp_file);
@@ -802,7 +801,7 @@ bool LLPreviewNotecard::loadNotecardText(const std::string& filename)
return false;
}
- LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ LLFILE* file = LLFile::fopen(filename, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!file)
{
LL_WARNS() << "Error opening " << filename << LL_ENDL;
@@ -833,7 +832,7 @@ bool LLPreviewNotecard::loadNotecardText(const std::string& filename)
bool LLPreviewNotecard::writeToFile(const std::string& filename)
{
- LLFILE* fp = LLFile::fopen(filename, "wb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("wb"));
if (!fp)
{
LL_WARNS() << "Unable to write to " << filename << LL_ENDL;
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 01167a43b8..3eadca7a40 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -662,7 +662,7 @@ bool LLScriptEdCore::loadScriptText(const std::string& filename)
return false;
}
- LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ LLFILE* file = LLFile::fopen(filename, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!file)
{
LL_WARNS() << "Error opening " << filename << LL_ENDL;
@@ -693,7 +693,7 @@ bool LLScriptEdCore::loadScriptText(const std::string& filename)
bool LLScriptEdCore::writeToFile(const std::string& filename)
{
- LLFILE* fp = LLFile::fopen(filename, "wb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("wb"));
if (!fp)
{
LL_WARNS() << "Unable to write to " << filename << LL_ENDL;
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index 3a894996e4..7d2828a872 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -54,7 +54,6 @@
#include "llviewertexturelist.h"
#include "llwindow.h"
#include "llworld.h"
-#include <boost/filesystem.hpp>
constexpr F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 2dc2810861..66872b104e 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 dd11099c69..2e918df910 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -265,7 +265,7 @@ public:
LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part);
- bool isHUDGroup() ;
+ bool isHUDGroup() const;
void clearDrawMap();
void validate();
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 958d8d6e85..00a34c802b 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -587,7 +587,7 @@ bool idle_startup()
std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg");
LLFILE* found_template = NULL;
- found_template = LLFile::fopen(message_template_path, "r"); /* Flawfinder: ignore */
+ found_template = LLFile::fopen(message_template_path, LLFILE_MODE("r")); /* Flawfinder: ignore */
#if LL_WINDOWS
// On the windows dev builds, unpackaged, the message_template.msg
@@ -596,7 +596,7 @@ bool idle_startup()
if (!found_template)
{
message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "app_settings", "message_template.msg");
- found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
+ found_template = LLFile::fopen(message_template_path.c_str(), LLFILE_MODE("r")); /* Flawfinder: ignore */
}
#elif LL_DARWIN
// On Mac dev builds, message_template.msg lives in:
@@ -606,7 +606,7 @@ bool idle_startup()
message_template_path =
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
"message_template.msg");
- found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */
+ found_template = LLFile::fopen(message_template_path.c_str(), LLFILE_MODE("r")); /* Flawfinder: ignore */
}
#endif
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 612af0d147..b0b929a3ef 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -157,7 +157,7 @@ protected:
LLAtomicS32 mBytesRead;
};
-class LLTextureCacheLocalFileWorker : public LLTextureCacheWorker
+class LLTextureCacheLocalFileWorker final : public LLTextureCacheWorker
{
public:
LLTextureCacheLocalFileWorker(LLTextureCache* cache, const std::string& filename, const LLUUID& id,
@@ -165,7 +165,7 @@ public:
S32 imagesize, // for writes
LLTextureCache::Responder* responder)
: LLTextureCacheWorker(cache, id, data, datasize, offset, imagesize, responder),
- mFileName(filename)
+ mFileName(fsyspath(filename))
{
}
@@ -174,19 +174,24 @@ public:
virtual bool doWrite();
private:
- std::string mFileName;
+ std::filesystem::path mFileName;
};
bool LLTextureCacheLocalFileWorker::doRead()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- S32 local_size = LLAPRFile::size(mFileName, mCache->getLocalAPRFilePool());
-
- if (local_size > 0 && mFileName.size() > 4)
+ S32 local_size = (S32)LLFile::size(mFileName);
+ if (local_size > 0 && mFileName.native().size() > 4)
{
mDataSize = local_size; // Only a complete file is valid
- std::string extension = mFileName.substr(mFileName.size() - 3, 3);
+#if LL_WINDOWS
+ std::wstring_view native_path = mFileName.native();
+ std::wstring_view extension = native_path.substr(native_path.size() - 3, 3);
+#else
+ std::string_view native_path = mFileName.native();
+ std::string_view extension = native_path.substr(native_path.size() - 3, 3);
+#endif
mImageFormat = LLImageBase::getCodecFromExtension(extension);
@@ -210,8 +215,7 @@ bool LLTextureCacheLocalFileWorker::doRead()
}
mReadData = (U8*)ll_aligned_malloc_16(mDataSize);
- S32 bytes_read = LLAPRFile::readEx(mFileName, mReadData, mOffset, mDataSize, mCache->getLocalAPRFilePool());
-
+ S32 bytes_read = (S32)LLFile::read(mFileName, mReadData, mOffset, mDataSize);
if (bytes_read != mDataSize)
{
// LL_WARNS() << "Error reading file from local cache: " << mFileName
@@ -235,7 +239,7 @@ bool LLTextureCacheLocalFileWorker::doWrite()
return false;
}
-class LLTextureCacheRemoteWorker : public LLTextureCacheWorker
+class LLTextureCacheRemoteWorker final : public LLTextureCacheWorker
{
public:
LLTextureCacheRemoteWorker(LLTextureCache* cache, const LLUUID& id,
@@ -296,7 +300,7 @@ bool LLTextureCacheRemoteWorker::doRead()
// Is it a JPEG2000 file?
{
local_filename = filename + ".j2c";
- local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
+ local_size = (S32)LLFile::size(local_filename);
if (local_size > 0)
{
mImageFormat = IMG_CODEC_J2C;
@@ -306,7 +310,7 @@ bool LLTextureCacheRemoteWorker::doRead()
if (local_size == 0)
{
local_filename = filename + ".jpg";
- local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
+ local_size = (S32)LLFile::size(local_filename);
if (local_size > 0)
{
mImageFormat = IMG_CODEC_JPEG;
@@ -317,7 +321,7 @@ bool LLTextureCacheRemoteWorker::doRead()
if (local_size == 0)
{
local_filename = filename + ".tga";
- local_size = LLAPRFile::size(local_filename, mCache->getLocalAPRFilePool());
+ local_size = (S32)LLFile::size(local_filename);
if (local_size > 0)
{
mImageFormat = IMG_CODEC_TGA;
@@ -346,12 +350,10 @@ bool LLTextureCacheRemoteWorker::doRead()
if (mReadData)
{
- S32 bytes_read = LLAPRFile::readEx( local_filename,
- mReadData,
- mOffset,
- mDataSize,
- mCache->getLocalAPRFilePool());
-
+ S32 bytes_read = (S32)LLFile::read(local_filename,
+ mReadData,
+ mOffset,
+ mDataSize);
if (bytes_read != mDataSize)
{
LL_WARNS() << "Error reading file from local cache: " << local_filename
@@ -410,8 +412,7 @@ bool LLTextureCacheRemoteWorker::doRead()
mReadData = (U8*)ll_aligned_malloc_16(size);
if (mReadData)
{
- S32 bytes_read = LLAPRFile::readEx(mCache->mHeaderDataFileName,
- mReadData, offset, size, mCache->getLocalAPRFilePool());
+ S32 bytes_read = (S32)LLFile::read(mCache->mHeaderDataFilePath, mReadData, offset, size);
if (bytes_read != size)
{
LL_WARNS() << "LLTextureCacheWorker: " << mID
@@ -445,10 +446,10 @@ bool LLTextureCacheRemoteWorker::doRead()
// Fourth state / stage : read the rest of the data from the UUID based cached file
if (!done && (mState == BODY))
{
- std::string filename = mCache->getTextureFileName(mID);
- S32 filesize = LLAPRFile::size(filename, mCache->getLocalAPRFilePool());
+ std::filesystem::path file_path = fsyspath(mCache->getTextureFileName(mID));
+ S32 filesize = (S32)LLFile::size(file_path);
- if (filesize && (filesize + TEXTURE_CACHE_ENTRY_SIZE) > mOffset)
+ if (filesize > 0 && (filesize + TEXTURE_CACHE_ENTRY_SIZE) > mOffset)
{
S32 max_datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize - mOffset;
mDataSize = llmin(max_datasize, mDataSize);
@@ -487,10 +488,9 @@ bool LLTextureCacheRemoteWorker::doRead()
mReadData = data;
// Read the data at last
- S32 bytes_read = LLAPRFile::readEx(filename,
- mReadData + data_offset,
- file_offset, file_size,
- mCache->getLocalAPRFilePool());
+ S32 bytes_read = (S32)LLFile::read(file_path,
+ mReadData + data_offset,
+ file_offset, file_size);
if (bytes_read != file_size)
{
LL_WARNS() << "LLTextureCacheWorker: " << mID
@@ -516,7 +516,7 @@ bool LLTextureCacheRemoteWorker::doRead()
{
// No body, we're done.
mDataSize = llmax(TEXTURE_CACHE_ENTRY_SIZE - mOffset, 0);
- LL_DEBUGS() << "No body file for: " << filename << LL_ENDL;
+ LL_DEBUGS() << "No body file for: " << file_path << LL_ENDL;
}
// Nothing else to do at that point...
done = true;
@@ -636,13 +636,13 @@ bool LLTextureCacheRemoteWorker::doWrite()
U8* padBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_CACHE_ENTRY_SIZE);
memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros
memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer
- bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool());
+ bytes_written = (S32)LLFile::write(mCache->mHeaderDataFilePath, padBuffer, offset, size);
ll_aligned_free_16(padBuffer);
}
else
{
// Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file
- bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool());
+ bytes_written = (S32)LLFile::write(mCache->mHeaderDataFilePath, mWriteData, offset, size);
}
if (bytes_written <= 0)
@@ -678,15 +678,11 @@ bool LLTextureCacheRemoteWorker::doWrite()
else
{
S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE;
-
{
// build the cache file name from the UUID
std::string filename = mCache->getTextureFileName(mID);
// LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL;
- S32 bytes_written = LLAPRFile::writeEx(filename,
- mWriteData + TEXTURE_CACHE_ENTRY_SIZE,
- 0, file_size,
- mCache->getLocalAPRFilePool());
+ S32 bytes_written = (S32)LLFile::write(filename, mWriteData + TEXTURE_CACHE_ENTRY_SIZE, 0, file_size);
if (bytes_written <= 0)
{
LL_WARNS() << "LLTextureCacheWorker: " << mID
@@ -866,9 +862,9 @@ std::string LLTextureCache::getLocalFileName(const LLUUID& id)
std::string LLTextureCache::getTextureFileName(const LLUUID& id)
{
- std::string idstr = id.asString();
- std::string delem = gDirUtilp->getDirDelimiter();
- std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr + ".texture";
+ char idstr[UUID_STR_LENGTH]{};
+ id.to_chars(idstr);
+ std::string filename = llformat("%s%s%c%s%s.texture", mTexturesDirName.c_str(), gDirUtilp->getDirDelimiter().c_str(), idstr[0], gDirUtilp->getDirDelimiter().c_str(), idstr);
return filename;
}
@@ -891,7 +887,7 @@ bool LLTextureCache::isInLocal(const LLUUID& id)
// Is it a JPEG2000 file?
{
local_filename = filename + ".j2c";
- local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool());
+ local_size = (S32)LLFile::size(local_filename);
if (local_size > 0)
{
return true ;
@@ -901,7 +897,7 @@ bool LLTextureCache::isInLocal(const LLUUID& id)
// If not, is it a jpeg file?
{
local_filename = filename + ".jpg";
- local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool());
+ local_size = (S32)LLFile::size(local_filename);
if (local_size > 0)
{
return true ;
@@ -911,7 +907,7 @@ bool LLTextureCache::isInLocal(const LLUUID& id)
// Hmm... What about a targa file? (used for UI texture mostly)
{
local_filename = filename + ".tga";
- local_size = LLAPRFile::size(local_filename, getLocalAPRFilePool());
+ local_size = (S32)LLFile::size(local_filename);
if (local_size > 0)
{
return true ;
@@ -944,7 +940,9 @@ const char* fast_cache_filename = "FastCache.cache";
void LLTextureCache::setDirNames(ELLPath location)
{
mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename);
- mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename);
+ mHeaderDataFilePath = fsyspath(gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename));
+ mHeaderEntriesFilePath = fsyspath(mHeaderEntriesFileName);
+
mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
mFastCacheFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, fast_cache_filename);
}
@@ -964,11 +962,10 @@ void LLTextureCache::purgeCache(ELLPath location, bool remove_dir)
if(LLFile::isdir(mTexturesDirName))
{
std::string file_name = gDirUtilp->getExpandedFilename(location, entries_filename);
- // mHeaderAPRFilePoolp because we are under header mutex, and can be in main thread
- LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
+ LLFile::remove(file_name);
file_name = gDirUtilp->getExpandedFilename(location, cache_filename);
- LLAPRFile::remove(file_name, mHeaderAPRFilePoolp);
+ LLFile::remove(file_name);
purgeAllTextures(true);
}
@@ -1069,10 +1066,9 @@ void LLTextureCache::readEntriesHeader()
{
// mHeaderEntriesInfo initializes to default values so safe not to read it
llassert_always(mHeaderAPRFile == NULL);
- if (LLAPRFile::isExist(mHeaderEntriesFileName, mHeaderAPRFilePoolp))
+ if (LLFile::isfile(mHeaderEntriesFilePath))
{
- LLAPRFile::readEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
- mHeaderAPRFilePoolp);
+ LLFile::read(mHeaderEntriesFilePath, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
}
else //create an empty entries header.
{
@@ -1088,7 +1084,7 @@ void LLTextureCache::setEntriesHeader()
// For simplicity we use predefined size of header, so if version string
// doesn't fit, either getEngineInfo() returned malformed string or
// sHeaderEncoderStringSize need to be increased.
- // Also take into accout that c_str() returns additional null character
+ // Also take into account that c_str() returns additional null character
LL_ERRS() << "Version string doesn't fit in header" << LL_ENDL;
}
@@ -1103,8 +1099,7 @@ void LLTextureCache::writeEntriesHeader()
llassert_always(mHeaderAPRFile == NULL);
if (!mReadOnly)
{
- LLAPRFile::writeEx(mHeaderEntriesFileName, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo),
- mHeaderAPRFilePoolp);
+ LLFile::write(mHeaderEntriesFilePath, (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
}
}
@@ -1208,8 +1203,7 @@ void LLTextureCache::writeEntryToHeaderImmediately(S32& idx, Entry& entry, bool
idx = -1 ;//mark the idx invalid.
return ;
}
-
- mHeaderAPRFile->seek(APR_SET, offset);
+ aprfile->seek(APR_SET, offset);
}
else
{
@@ -1618,7 +1612,7 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
gDirUtilp->deleteFilesInDir(mTexturesDirName, mask); // headers, fast cache
if (purge_directories)
{
- LLFile::rmdir(mTexturesDirName);
+ LLFile::remove(mTexturesDirName);
}
}
mHeaderIDMap.clear();
@@ -1798,8 +1792,7 @@ void LLTextureCache::purgeTextures(bool validate)
{
std::string filename = getTextureFileName(entries[idx].mID);
LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL;
- // mHeaderAPRFilePoolp because this is under header mutex in main thread
- S32 bodysize = LLAPRFile::size(filename, mHeaderAPRFilePoolp);
+ S32 bodysize = (S32)LLFile::size(filename);
if (bodysize != entries[idx].mBodySize)
{
LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize << filename << LL_ENDL;
@@ -2150,7 +2143,7 @@ void LLTextureCache::openFastCache(bool first_time)
mFastCachePadBuffer = (U8*)ll_aligned_malloc_16(TEXTURE_FAST_CACHE_ENTRY_SIZE);
}
mFastCachePoolp = new LLVolatileAPRPool(); // is_local= true by default, so not thread safe by default
- if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp))
+ if (LLFile::isfile(mFastCacheFileName))
{
mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
}
@@ -2233,9 +2226,7 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id)
mTexturesSizeMap.erase(id);
}
mHeaderIDMap.erase(id);
- // We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
- // but getLocalAPRFilePool() is not safe, it might be in use by worker
- LLAPRFile::remove(getTextureFileName(id), mHeaderAPRFilePoolp);
+ LLFile::remove(getTextureFileName(id));
}
//called after mHeaderMutex is locked.
@@ -2248,9 +2239,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
if (entry.mBodySize == 0) // Always attempt to remove when mBodySize > 0.
{
// Sanity check. Shouldn't exist when body size is 0.
- // We are inside header's mutex so mHeaderAPRFilePoolp is safe to use,
- // but getLocalAPRFilePool() is not safe, it might be in use by worker
- if (LLAPRFile::isExist(filename, mHeaderAPRFilePoolp))
+ if (LLFile::isfile(filename))
{
LL_WARNS("TextureCache") << "Entry has body size of zero but file " << filename << " exists. Deleting this file, too." << LL_ENDL;
}
@@ -2270,7 +2259,7 @@ void LLTextureCache::removeEntry(S32 idx, Entry& entry, std::string& filename)
if (file_maybe_exists)
{
- LLAPRFile::remove(filename, mHeaderAPRFilePoolp);
+ LLFile::remove(filename);
}
}
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index faf722dc8f..fd4c4001b6 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -218,7 +218,8 @@ private:
// HEADERS (Include first mip)
std::string mHeaderEntriesFileName;
- std::string mHeaderDataFileName;
+ std::filesystem::path mHeaderEntriesFilePath;
+ std::filesystem::path mHeaderDataFilePath;
std::string mFastCacheFileName;
EntriesInfo mHeaderEntriesInfo;
std::set<S32> mFreeList; // deleted entries
diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp
index c1ec5fa183..c401a00fd7 100644
--- a/indra/newview/lltoolbarview.cpp
+++ b/indra/newview/lltoolbarview.cpp
@@ -420,7 +420,7 @@ void LLToolBarView::saveToolbars() const
if(!output_node->isNull())
{
const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml");
- LLFILE *fp = LLFile::fopen(filename, "w");
+ LLFILE *fp = LLFile::fopen(filename, LLFILE_MODE("w"));
if (fp != NULL)
{
LLXMLNode::writeHeaderToFile(fp);
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..867d47c893 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -182,7 +182,7 @@ void LLViewerAssetStorage::storeAssetData(
else
{
// LLAssetStorage metric: Successful Request
- S32 size = LLFileSystem::getFileSize(asset_id, asset_type);
+ S32 size = vfile.getSize();
const char *message = "Added to upload queue";
reportMetric( asset_id, asset_type, LLStringUtil::null, LLUUID::null, size, MR_OKAY, __FILE__, __LINE__, message );
@@ -279,7 +279,7 @@ void LLViewerAssetStorage::storeAssetData(
LL_DEBUGS("AssetStorage") << "ASSET_ID: " << asset_id << LL_ENDL;
S32 size = 0;
- LLFILE* fp = LLFile::fopen(filename, "rb");
+ LLFILE* fp = LLFile::fopen(filename, LLFILE_MODE("rb"));
if (fp)
{
fseek(fp, 0, SEEK_END);
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 91f3dcabe8..fa9a07ce22 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -45,11 +45,7 @@
#include "llappviewer.h"
#include "llviewerstats.h"
#include "llfilesystem.h"
-#include "llgesturemgr.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewgesture.h"
#include "llcoproceduremanager.h"
-#include "llthread.h"
#include "llkeyframemotion.h"
#include "lldatapacker.h"
#include "llvoavatarself.h"
@@ -405,6 +401,7 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
std::string errorMessage;
std::string errorLabel;
+ std::error_code ec;
bool error = false;
@@ -475,30 +472,38 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
error = true;
// read from getFileName()
- LLAPRFile infile;
- infile.open(getFileName(),LL_APR_RB);
- if (!infile.getFileHandle())
+ LLFile infile(getFileName(), LLFile::in | LLFile::binary, ec);
+ if (ec || !infile)
{
LL_WARNS() << "Couldn't open file for reading: " << getFileName() << LL_ENDL;
errorMessage = llformat("Failed to open animation file %s\n", getFileName().c_str());
}
else
{
- S32 size = LLAPRFile::size(getFileName());
+ S64 size = infile.size(ec);
+ if (ec || size <= 0)
+ {
+ LLError::LLUserWarningMsg::showMissingFiles();
+ LL_ERRS() << "Invalid file" << LL_ENDL;
+ }
+ else if (size > INT_MAX)
+ {
+ LL_ERRS() << "File " << getFileName() << " is too big, size: " << size << LL_ENDL;
+ }
U8* buffer = new(std::nothrow) U8[size];
if (!buffer)
{
LLError::LLUserWarningMsg::showOutOfMemory();
LL_ERRS() << "Bad memory allocation for buffer, size: " << size << LL_ENDL;
}
- S32 size_read = infile.read(buffer,size);
- if (size_read != size)
+ S64 size_read = infile.read(buffer, size, ec);
+ if (ec || size_read != size)
{
errorMessage = llformat("Failed to read animation file %s: wanted %d bytes, got %d\n", getFileName().c_str(), size, size_read);
}
else
{
- LLDataPackerBinaryBuffer dp(buffer, size);
+ LLDataPackerBinaryBuffer dp(buffer, (S32)size);
LLKeyframeMotion *motionp = new LLKeyframeMotion(getAssetId());
motionp->setCharacter(gAgentAvatarp);
if (motionp->deserialize(dp, getAssetId(), false))
@@ -544,18 +549,17 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
setAssetType(assetType);
// copy this file into the cache for upload
- S32 file_size;
- LLAPRFile infile;
- infile.open(filename, LL_APR_RB, NULL, &file_size);
- if (infile.getFileHandle())
+ LLFile infile(filename, LLFile::in | LLFile::binary, ec);
+ if (!ec && infile.size(ec) > 0)
{
LLFileSystem file(getAssetId(), assetType, LLFileSystem::APPEND);
+ S64 read_bytes;
const S32 buf_size = 65536;
U8 copy_buf[buf_size];
- while ((file_size = infile.read(copy_buf, buf_size)))
+ while (((read_bytes = infile.read(copy_buf, buf_size, ec))) > 0)
{
- file.write(copy_buf, file_size);
+ file.write(copy_buf, (S32)read_bytes);
}
}
else
@@ -569,7 +573,6 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
}
return LLSD();
-
}
//=========================================================================
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/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index d7b43e1789..a8ed79a8cc 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -446,16 +446,6 @@ static bool handleUploadBakedTexOldChanged(const LLSD& newvalue)
return true;
}
-
-static bool handleWLSkyDetailChanged(const LLSD&)
-{
- if (gSky.mVOWLSkyp.notNull())
- {
- gSky.mVOWLSkyp->updateGeometry(gSky.mVOWLSkyp->mDrawable);
- }
- return true;
-}
-
static bool handleRepartition(const LLSD&)
{
if (gPipeline.isInit())
@@ -840,6 +830,7 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "RenderUIBuffer", handleWindowResized);
setting_setup_signal_listener(gSavedSettings, "RenderDepthOfField", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderFSAAType", handleReleaseGLBufferChanged);
+ setting_setup_signal_listener(gSavedSettings, "RenderHighPrecisionPostProcess", handleReleaseGLBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderSpecularResX", handleLUTBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged);
setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged);
@@ -901,7 +892,6 @@ void settings_setup_listeners()
setting_setup_signal_listener(gSavedSettings, "MuteVoice", handleAudioVolumeChanged);
setting_setup_signal_listener(gSavedSettings, "MuteAmbient", handleAudioVolumeChanged);
setting_setup_signal_listener(gSavedSettings, "MuteUI", handleAudioVolumeChanged);
- setting_setup_signal_listener(gSavedSettings, "WLSkyDetail", handleWLSkyDetailChanged);
setting_setup_signal_listener(gSavedSettings, "JoystickAxis0", handleJoystickChanged);
setting_setup_signal_listener(gSavedSettings, "JoystickAxis1", handleJoystickChanged);
setting_setup_signal_listener(gSavedSettings, "JoystickAxis2", handleJoystickChanged);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index ce59e844ec..6b1ec4bbbe 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1139,15 +1139,12 @@ std::string getProfileStatsFilename()
// same second), may produce (e.g.) sec==61, but avoids collisions and
// preserves chronological filename sort order.
std::string name;
- std::error_code ec;
do
{
// base + missing 2-digit seconds, append ".json"
// post-increment sec in case we have to try again
name = stringize(base, std::setw(2), std::setfill('0'), sec++, ".json");
- } while (std::filesystem::exists(fsyspath(name), ec));
- // Ignoring ec means we might potentially return a name that does already
- // exist -- but if we can't check its existence, what more can we do?
+ } while (LLFile::exists(name));
return name;
}
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 3c79f0b21c..5741d7f5fb 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -1430,7 +1430,7 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
// file in app_settings is supposed to be up to date
// this is only for the file from user_settings
LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL;
- LLFILE *fp = LLFile::fopen(filename, "w");
+ LLFILE *fp = LLFile::fopen(filename, LLFILE_MODE("w"));
if (fp != NULL)
{
LLXMLNode::writeHeaderToFile(fp);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 071a66209b..30b2dafb8f 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())
@@ -1833,12 +1834,11 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
user_data_path_cache += gDirUtilp->getDirDelimiter();
// See if the plugin executable exists
- llstat s;
- if(LLFile::stat(launcher_name, &s))
+ if (!LLFile::isfile(launcher_name))
{
LL_WARNS_ONCE("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL;
}
- else if(LLFile::stat(plugin_name, &s))
+ else if (!LLFile::isfile(plugin_name))
{
LL_WARNS_ONCE("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL;
}
@@ -2197,16 +2197,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 6a5e7896c0..abc4856261 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/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 0e9bfb102f..423bb5f31d 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -1161,7 +1161,7 @@ void handle_compress_image()
// so doing dirty, but OS independent fopen and fseek
size_t get_file_size(std::string &filename)
{
- LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
+ LLFILE* file = LLFile::fopen(filename, LLFILE_MODE("rb")); /*Flawfinder: ignore*/
if (!file)
{
LL_WARNS() << "Error opening " << filename << LL_ENDL;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1675c44c5c..0f4cbdd25c 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -310,6 +310,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 +368,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()) ;
@@ -1508,10 +1500,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 +1534,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 +1842,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 +1862,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 +4175,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 +6486,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 +6498,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 +6578,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 +6598,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 +6667,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 +7438,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 +7460,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 +7482,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 +7523,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;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index a9c2db60e4..cccf59a319 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;
@@ -630,10 +632,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 +683,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,6 +780,21 @@ 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;
public:
// Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties
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 83b8aa8d03..fb6fa8bac4 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -312,7 +312,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 cf92850762..17d2edee4d 100755..100644
--- 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/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index cd70f8f9b9..cd70f8f9b9 100755..100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp
index 58065ecce5..a183d7c8de 100644
--- a/indra/newview/llviewerstatsrecorder.cpp
+++ b/indra/newview/llviewerstatsrecorder.cpp
@@ -194,7 +194,7 @@ void LLViewerStatsRecorder::writeToLog( F32 interval )
// Open the data file
makeStatsFileName();
- mStatsFile = LLFile::fopen(mStatsFileName, "wb");
+ mStatsFile = LLFile::fopen(mStatsFileName, LLFILE_MODE("wb"));
if (mStatsFile)
{
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 0980c4a291..a3c241456d 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -33,9 +33,6 @@
#include <iostream>
#include <fstream>
#include <algorithm>
-#include <boost/filesystem.hpp>
-#include <boost/lambda/core.hpp>
-#include <boost/regex.hpp>
#include "llagent.h"
#include "llagentcamera.h"
@@ -1335,7 +1332,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);
@@ -3397,13 +3394,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;
@@ -3421,12 +3416,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);
@@ -3855,6 +3853,7 @@ void LLViewerWindow::updateUI()
void LLViewerWindow::updateLayout()
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
if (gFloaterTools != NULL
&& tool != NULL
@@ -4334,15 +4333,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);
}
@@ -4366,7 +4365,6 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
mWindow->delayInputProcessing();
}
-
void LLViewerWindow::performPick()
{
if (!mPicks.empty())
@@ -4400,8 +4398,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
@@ -4409,7 +4408,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();
@@ -4837,14 +4836,10 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save
return;
}
-// Check if there is enough free space to save snapshot
-#ifdef LL_WINDOWS
- boost::filesystem::path b_path(ll_convert<std::wstring>(lastSnapshotDir));
-#else
- boost::filesystem::path b_path(lastSnapshotDir);
-#endif
- boost::system::error_code ec;
- if (!boost::filesystem::is_directory(b_path, ec) || ec.failed())
+ // Check if there is enough free space to save snapshot
+ std::filesystem::path b_path = fsyspath(lastSnapshotDir);
+ std::error_code ec;
+ if (!std::filesystem::is_directory(b_path, ec) || ec)
{
LLSD args;
args["PATH"] = lastSnapshotDir;
@@ -4853,8 +4848,8 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save
failure_cb();
return;
}
- boost::filesystem::space_info b_space = boost::filesystem::space(b_path, ec);
- if (ec.failed())
+ std::filesystem::space_info b_space = std::filesystem::space(b_path, ec);
+ if (ec)
{
LLSD args;
args["PATH"] = lastSnapshotDir;
@@ -6138,14 +6133,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/llvocache.cpp b/indra/newview/llvocache.cpp
index 5d456b1a19..cdc41baa88 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -1250,7 +1250,7 @@ void LLVOCache::removeCache(ELLPath location, bool started)
std::string cache_dir = gDirUtilp->getExpandedFilename(location, object_cache_dirname);
LL_INFOS() << "Removing cache at " << cache_dir << LL_ENDL;
gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files
- LLFile::rmdir(cache_dir);
+ LLFile::remove(cache_dir);
clearCacheInMemory();
mInitialized = false;
@@ -1370,7 +1370,7 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry)
std::string filename;
getObjectCacheFilename(entry->mHandle, filename);
LL_WARNS("GLTF", "VOCache") << "Removing object cache for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL;
- LLAPRFile::remove(filename, mLocalAPRFilePoolp);
+ LLFile::remove(filename);
// Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry.
// as such this now includes the generic extras
@@ -1394,7 +1394,7 @@ void LLVOCache::readCacheHeader()
clearCacheInMemory();
bool success = true ;
- if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp))
+ if (LLFile::isfile(mHeaderFileName))
{
LLAPRFile apr_file(mHeaderFileName, APR_READ|APR_BINARY, mLocalAPRFilePoolp);
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index d132cbfa36..e58a6577f1 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -943,8 +943,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon()
gDirUtilp->append(exe_path, "SLVoice");
#endif
// See if the vivox executable exists
- llstat s;
- if (!LLFile::stat(exe_path, &s))
+ if (LLFile::isfile(exe_path))
{
// vivox executable exists. Build the command line and launch the daemon.
LLProcess::Params params;
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 085e386ec9..d1de2f55da 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -2549,10 +2549,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 +2895,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 +2922,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
LLWebRTCVoiceClient::getInstance()->updatePosition();
LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true);
}
+ else
+ {
+ mWebRTCAudioInterface->setMute(mMuted);
+ }
}
break;
}
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/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index b5ee42f36c..98d771f8da 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -36,17 +36,16 @@
#include "llenvironment.h"
#include "llsettingssky.h"
-constexpr U32 MIN_SKY_DETAIL = 8;
-constexpr U32 MAX_SKY_DETAIL = 180;
+constexpr U32 SKY_DETAIL = 18; // Any lower and there will be artifacts
inline U32 LLVOWLSky::getNumStacks(void)
{
- return llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail")));
+ return SKY_DETAIL;
}
inline U32 LLVOWLSky::getNumSlices(void)
{
- return 2 * llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail")));
+ return 2 * SKY_DETAIL;
}
inline U32 LLVOWLSky::getStripsNumVerts(void)
diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp
index 614d1afc2a..072743505f 100644
--- a/indra/newview/llwatchdog.cpp
+++ b/indra/newview/llwatchdog.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "llwatchdog.h"
+#include "llmutex.h"
#include "llthread.h"
#include "llappviewer.h"
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..100644
--- 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 259ea0c84f..3b72e512da 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -820,9 +820,8 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
-
- static LLCachedControl<bool> has_hdr(gSavedSettings, "RenderHDREnabled", true);
- bool hdr = gGLManager.mGLVersion > 4.05f && has_hdr();
+ bool has_hdr = gSavedSettings.getBOOL("RenderHDREnabled");
+ bool hdr = gGLManager.mGLVersion > 4.05f && has_hdr;
if (mRT == &mMainRT)
{ // hacky -- allocate auxillary buffer
@@ -888,6 +887,8 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
if (!gCubeSnapshot) // hack to not re-allocate various targets for cube snapshots
{
+ U32 post_color_fmt = gSavedSettings.getBOOL("RenderHighPrecisionPostProcess") ? GL_RGBA16F : GL_RGBA;
+
if (RenderUIBuffer)
{
if (!mUIScreen.allocate(resX, resY, GL_RGBA))
@@ -898,10 +899,10 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
if (RenderFSAAType > 0)
{
- if (!mFXAAMap.allocate(resX, resY, GL_RGBA)) return false;
+ if (!mFXAAMap.allocate(resX, resY, post_color_fmt)) return false;
if (RenderFSAAType == 2)
{
- if (!mSMAABlendBuffer.allocate(resX, resY, GL_RGBA, false)) return false;
+ if (!mSMAABlendBuffer.allocate(resX, resY, post_color_fmt, false)) return false;
}
}
else
@@ -922,8 +923,8 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY)
mSceneMap.release();
}
- mPostPingMap.allocate(resX, resY, GL_RGBA);
- mPostPongMap.allocate(resX, resY, GL_RGBA);
+ mPostPingMap.allocate(resX, resY, post_color_fmt);
+ mPostPongMap.allocate(resX, resY, post_color_fmt);
// The water exclusion mask needs its own depth buffer so we can take care of the problem of multiple water planes.
// Should we ever make water not just a plane, it also aids with that as well as the water planes will be rendered into the mask.
@@ -5535,7 +5536,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/res/have_artwork_bundle.marker b/indra/newview/res/have_artwork_bundle.marker
index 1dbb238d53..1dbb238d53 100755..100644
--- a/indra/newview/res/have_artwork_bundle.marker
+++ b/indra/newview/res/have_artwork_bundle.marker
diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc
index dc2ba5f171..dc2ba5f171 100755..100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
diff --git a/indra/newview/secondlife-i686.supp b/indra/newview/secondlife-i686.supp
index 863c8364ab..863c8364ab 100755..100644
--- a/indra/newview/secondlife-i686.supp
+++ b/indra/newview/secondlife-i686.supp
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index 3ba772e8d7..aff4111d35 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -76,19 +76,19 @@
height="16"
increment="1"
initial_value="8"
- label="Post process quality:"
+ label="Glow quality:"
label_width="185"
layout="topleft"
left="30"
min_val="8"
max_val="9"
- name="RenderPostProcess"
+ name="GlowResolution"
show_text="false"
top_delta="16"
width="300">
<slider.commit_callback
function="Pref.UpdateSliderText"
- parameter="PostProcessText" />
+ parameter="GlowResolutionText" />
</slider>
<text
type="string"
@@ -96,7 +96,7 @@
follows="left|top"
height="16"
layout="topleft"
- name="PostProcessText"
+ name="GlowResolutionText"
top_delta="0"
left_delta="304"
width="65">
@@ -689,25 +689,25 @@
</check_box>
<slider
- control_name="WLSkyDetail"
+ control_name="RenderHighPrecisionPostProcess"
decimal_digits="0"
follows="left|top"
height="16"
- increment="8"
+ increment="1"
initial_value="160"
- label="Sky:"
+ label="Post Process Quality:"
label_width="145"
layout="topleft"
left="420"
- min_val="16"
- max_val="128"
- name="SkyMeshDetail"
+ min_val="0"
+ max_val="1"
+ name="RenderPostProcess"
show_text="false"
top_delta="22"
width="260">
<slider.commit_callback
function="Pref.UpdateSliderText"
- parameter="SkyMeshDetailText" />
+ parameter="PostProcessText" />
</slider>
<text
type="string"
@@ -716,7 +716,7 @@
height="16"
layout="topleft"
left_delta="264"
- name="SkyMeshDetailText"
+ name="PostProcessText"
text_readonly_color="LabelDisabledColor"
top_delta="0"
width="65">
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_gallery_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
index fb68193006..fb68193006 100755..100644
--- a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index dbd513afe8..d278bac075 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -4425,9 +4425,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/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
index 90bdea93fa..018306826e 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
@@ -60,10 +60,22 @@
name="Large(512x512)"
value="[i512,i512]" />
<combo_box.item
+ label="Wide (1024x512)"
+ name="Wide(1024x512)"
+ value="[i1024,i512]" />
+ <combo_box.item
label="Huge (1024x1024)"
name="Huge(1024x1024)"
value="[i1024,i1024]" />
<combo_box.item
+ label="Full Wide (2048x1024)"
+ name="Full(2048x1024)"
+ value="[i2048,i1024]" />
+ <combo_box.item
+ label="Full (2048x2048)"
+ name="Full(2048x2048)"
+ value="[i2048,i2048]" />
+ <combo_box.item
label="Current Window"
name="CurrentWindow"
value="[i0,i0]" />
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
index 52f9068264..0a56a7b638 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_local.xml
@@ -75,6 +75,26 @@
name="1600x1200"
value="[i1600,i1200]" />
<combo_box.item
+ label="1920x1080"
+ name="1920x1080"
+ value="[i1920,i1080]" />
+ <combo_box.item
+ label="2560x1440"
+ name="2560x1440"
+ value="[i2560,i1440]" />
+ <combo_box.item
+ label="3840x2160"
+ name="3840x2160"
+ value="[i3840,i2160]" />
+ <combo_box.item
+ label="5120x2880"
+ name="5120x2880"
+ value="[i5120,i2880]" />
+ <combo_box.item
+ label="7680x4320"
+ name="7680x4320"
+ value="[i7680,i4320]" />
+ <combo_box.item
label="Custom"
name="Custom"
value="[i-1,i-1]" />
diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h
index 8027f95728..a38746759f 100644
--- a/indra/test/namedtempfile.h
+++ b/indra/test/namedtempfile.h
@@ -12,26 +12,29 @@
#if ! defined(LL_NAMEDTEMPFILE_H)
#define LL_NAMEDTEMPFILE_H
+#include "fsyspath.h"
#include "llerror.h"
#include "llstring.h"
#include "stringize.h"
#include <string>
-#include <boost/filesystem.hpp>
-#include <boost/filesystem/fstream.hpp>
-#include <boost/noncopyable.hpp>
+#include <fstream>
#include <functional>
#include <iostream>
#include <sstream>
#include <string_view>
+#include <random>
/**
* Create a text file with specified content "somewhere in the
* filesystem," cleaning up when it goes out of scope.
*/
-class NamedTempFile: public boost::noncopyable
+class NamedTempFile
{
LOG_CLASS(NamedTempFile);
public:
+ NamedTempFile(const NamedTempFile&) = delete;
+ NamedTempFile& operator=(const NamedTempFile&) = delete;
+
NamedTempFile(const std::string_view& pfx,
const std::string_view& content,
const std::string_view& sfx=std::string_view(""))
@@ -62,16 +65,16 @@ public:
virtual ~NamedTempFile()
{
- boost::filesystem::remove(mPath);
+ std::filesystem::remove(mPath);
}
- std::string getName() const { return mPath.string(); }
+ const std::filesystem::path& getPath() const { return mPath; }
template <typename CALLABLE>
void peep_via(CALLABLE&& callable) const
{
std::forward<CALLABLE>(callable)(stringize("File '", mPath, "' contains:"));
- boost::filesystem::ifstream reader(mPath, std::ios::binary);
+ std::ifstream reader(mPath, std::ios::binary);
std::string line;
while (std::getline(reader, line))
std::forward<CALLABLE>(callable)(line);
@@ -94,23 +97,27 @@ public:
return out;
}
- static boost::filesystem::path temp_path(const std::string_view& pfx="",
+ static std::filesystem::path temp_path(const std::string_view& pfx="",
const std::string_view& sfx="")
{
// This variable is set by GitHub actions and is the recommended place
// to put temp files belonging to an actions job.
const char* RUNNER_TEMP = getenv("RUNNER_TEMP");
- boost::filesystem::path tempdir{
+ std::filesystem::path tempdir{
// if RUNNER_TEMP is set and not empty
(RUNNER_TEMP && *RUNNER_TEMP)?
- boost::filesystem::path(RUNNER_TEMP) : // use RUNNER_TEMP if available
- boost::filesystem::temp_directory_path()}; // else canonical temp dir
- boost::filesystem::path tempname{
- // use filename template recommended by unique_path() doc, but
- // with underscores instead of hyphens: some use cases involve
- // temporary Python scripts
- tempdir / stringize(pfx, "%%%%_%%%%_%%%%_%%%%", sfx) };
- return boost::filesystem::unique_path(tempname);
+ fsyspath::path(RUNNER_TEMP) : // use RUNNER_TEMP if available
+ std::filesystem::temp_directory_path()}; // else canonical temp dir
+
+ static std::mt19937 random_generator{std::random_device{}()};
+ static std::uniform_int_distribution<> distribution{0, std::numeric_limits<uint8_t>::max()};
+ std::string tempname{};
+ static constexpr auto num_bits = 128;
+ for (auto i = 0; i < (num_bits / std::numeric_limits<uint8_t>::digits); ++i) {
+ tempname += llformat("%02x", distribution(random_generator));
+ }
+ tempname = std::string(pfx) + tempname + std::string(sfx);
+ return tempdir / tempname;
}
protected:
@@ -120,12 +127,12 @@ protected:
{
// Create file in a temporary place.
mPath = temp_path(pfx, sfx);
- boost::filesystem::ofstream out{ mPath, std::ios::binary };
+ std::ofstream out{ mPath, std::ios::binary };
// Write desired content.
func(out);
}
- boost::filesystem::path mPath;
+ std::filesystem::path mPath;
};
/**
diff --git a/indra/test/test.cpp b/indra/test/test.cpp
index 5b36bb618d..cee8b84438 100644
--- a/indra/test/test.cpp
+++ b/indra/test/test.cpp
@@ -79,7 +79,7 @@ public:
RecordToTempFile()
: LLError::Recorder(),
mTempFile("log", ""),
- mFile(mTempFile.getName().c_str())
+ mFile(mTempFile.getPath())
{
}
@@ -97,13 +97,13 @@ public:
void reset()
{
mFile.close();
- mFile.open(mTempFile.getName().c_str());
+ mFile.open(mTempFile.getPath());
}
void replay(std::ostream& out)
{
mFile.close();
- llifstream inf(mTempFile.getName().c_str());
+ llifstream inf(mTempFile.getPath());
std::string line;
while (std::getline(inf, line))
{
diff --git a/scripts/code_tools/fix_whitespace.py b/scripts/code_tools/fix_whitespace.py
index d5f7ce1cce..d5f7ce1cce 100644..100755
--- a/scripts/code_tools/fix_whitespace.py
+++ b/scripts/code_tools/fix_whitespace.py
diff --git a/scripts/code_tools/fix_xml_indentations.py b/scripts/code_tools/fix_xml_indentations.py
index a196b0b7d4..a196b0b7d4 100644..100755
--- a/scripts/code_tools/fix_xml_indentations.py
+++ b/scripts/code_tools/fix_xml_indentations.py
diff --git a/scripts/code_tools/modified-strings.sh b/scripts/code_tools/modified-strings.sh
index 932b0a4bfc..932b0a4bfc 100644..100755
--- a/scripts/code_tools/modified-strings.sh
+++ b/scripts/code_tools/modified-strings.sh
diff --git a/scripts/code_tools/modified_strings.py b/scripts/code_tools/modified_strings.py
index c777fc8c0d..c777fc8c0d 100644..100755
--- a/scripts/code_tools/modified_strings.py
+++ b/scripts/code_tools/modified_strings.py
diff --git a/scripts/content_tools/anim_tool.py b/scripts/content_tools/anim_tool.py
index 07159a8052..07159a8052 100644..100755
--- a/scripts/content_tools/anim_tool.py
+++ b/scripts/content_tools/anim_tool.py
diff --git a/scripts/content_tools/arche_tool.py b/scripts/content_tools/arche_tool.py
index 9979c61b21..9979c61b21 100644..100755
--- a/scripts/content_tools/arche_tool.py
+++ b/scripts/content_tools/arche_tool.py
diff --git a/scripts/content_tools/dae_tool.py b/scripts/content_tools/dae_tool.py
index 5286c37de3..5286c37de3 100644..100755
--- a/scripts/content_tools/dae_tool.py
+++ b/scripts/content_tools/dae_tool.py
diff --git a/scripts/content_tools/skel_tool.py b/scripts/content_tools/skel_tool.py
index 604d2b7db9..604d2b7db9 100644..100755
--- a/scripts/content_tools/skel_tool.py
+++ b/scripts/content_tools/skel_tool.py
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 40ba2cc6b6..40ba2cc6b6 100755..100644
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index baa4f3f12b..baa4f3f12b 100755..100644
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
diff --git a/scripts/metrics/slp_conv.py b/scripts/metrics/slp_conv.py
index 25f9a8c060..25f9a8c060 100644..100755
--- a/scripts/metrics/slp_conv.py
+++ b/scripts/metrics/slp_conv.py
diff --git a/scripts/metrics/viewer_asset_logs.py b/scripts/metrics/viewer_asset_logs.py
index 4fb9fd15b3..4fb9fd15b3 100644..100755
--- a/scripts/metrics/viewer_asset_logs.py
+++ b/scripts/metrics/viewer_asset_logs.py
diff --git a/scripts/perf/logsdir.py b/scripts/perf/logsdir.py
index 5ab45a28b6..5ab45a28b6 100644..100755
--- a/scripts/perf/logsdir.py
+++ b/scripts/perf/logsdir.py
diff --git a/scripts/perf/perfbot_run.py b/scripts/perf/perfbot_run.py
index 55ea2fae66..55ea2fae66 100644..100755
--- a/scripts/perf/perfbot_run.py
+++ b/scripts/perf/perfbot_run.py
diff --git a/scripts/perf/profile_cmp.py b/scripts/perf/profile_cmp.py
index 9dbfa3145b..9dbfa3145b 100644..100755
--- a/scripts/perf/profile_cmp.py
+++ b/scripts/perf/profile_cmp.py
diff --git a/scripts/perf/profile_csv.py b/scripts/perf/profile_csv.py
index 7a6b2b338e..7a6b2b338e 100644..100755
--- a/scripts/perf/profile_csv.py
+++ b/scripts/perf/profile_csv.py
diff --git a/scripts/perf/profile_pretty.py b/scripts/perf/profile_pretty.py
index 405b14b373..405b14b373 100644..100755
--- a/scripts/perf/profile_pretty.py
+++ b/scripts/perf/profile_pretty.py
diff --git a/scripts/templates/template-cpp.cpp b/scripts/templates/template-cpp.cpp
index 8ee04942bf..8ee04942bf 100755..100644
--- a/scripts/templates/template-cpp.cpp
+++ b/scripts/templates/template-cpp.cpp
diff --git a/scripts/templates/template-h.h b/scripts/templates/template-h.h
index d7677c256b..d7677c256b 100755..100644
--- a/scripts/templates/template-h.h
+++ b/scripts/templates/template-h.h